17141200320
发表于 2024-1-8 09:16:36
第十三集 简易多任务处理
应用模块化的编程(.c+.h)
1、创建程序文件三步
1.1新建文件并保存
1.2添加工程
1.3添加引用路径
2、引用定义都在.h文件
sbit 名称=P10;
#define名称 P10
3、函数定义三步
定义
声明
调用
修饰符extern用在变量或者函数的声明前,用来说明”此变量/函数是在别处定义的,要在此处引用“ 。
举例1:如果文件a.c需要引用b.c中变量int V,就可以在a.c中申明extern int V,然后就可以引用变量V.
举例2:如果文件a.c需要引用b.c中变量int V,就可以在b.h中申明extern int V,然后a.c调用b.h就可以引用变量V.
注意extern修饰的变量不能赋初值
4、bdata位寻址变量的使用
a.c a.h
u8bdataLED=0X00; extenu8 bdata LED;
sbitLED0 = LED^0; extenbit LED0;
sbitLED1 = LED^1; extenbit LED1;
5、用模块化编程方式将LED&数码管、按健、蜂鸣器、定时器集成在一个工程中,完成多个功能。
6、模块化编程中讲了for循环应用
u8i=0;
u8t=0;
for (i=0;i<8;i++) //i<8,i后自加1次,条件为真,执行for循环内部语句,i=8,i不小于,条件不为成立,跳出循环语句。
{
t++;
}
7、讲了static用法
voidSEG_fre(void )
{
staticu8num = 0 ;//变量前有static修饰时, num赋初值只1次,下次就为1,再下次为2 。
if(num<7)
{
;
}
num++;
}
8、讲了按键状态机应用
17141200320
发表于 2024-1-9 11:14:47
第十四讲 矩阵按键
1、讲了按键原理图
按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。
第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
第三步:行列组合一下就可判断出是哪一个按键按下了。
2、矩阵按键部分程序
/************延时函数*****************/
void MateixKEY_delay(void)
{
u8 i =60;
while(--i);
}
/*****矩阵按键读取当前是哪一个按钮按下*********/
u8MateixKEY_Read(void)
{
u8 keystate; //表示当前的按键的状态值
//第一步:现将P0.0-P0.3输出低电平◇P0.6-P0.7输出高电平◇如果有按键按下◇
MateixKEY= 0xC0; //1100 0000
MateixKEY_delay();
keystate = ( MateixKEY ^ 0xC0);// 0100 0000 ^1100 0000 =1000 000
//第二步◇现将P0.0-P0.3输出高电平◇P0.6-P0.7输出低电平◇如果有按键按下,按下的那一行IO就会变成低电平。
MateixKEY= OXOf; //0000 1111
MateixKEY_delay();
keystate |=(MateixKEY ^OX0f); //00001110 ^ 00001111 = 0000 0001 | 1000 0000 =0x81。
//第三步:行列组合一下就可以判断出是哪个按键按下了。
printf("0x%02x\r\n",keystate);
return keystate:
}
voidmain()
{
u8 KEY_NUM = 0; //
sys_init () ;
usb_init () ;
Timer0_Init ();
EA = 1;
LED = 0XFF;
while(1)
{
if(DeviceState !=DEVSTATE_CONFIGURED)
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if(TIM_10MS_Flag==1 )
{
TIM_10MS_Flag=0;
KEY_NUM=MateixKEY_Read();
SEG7 = voidmain()
{
u8 KEY_NUM = 0; //
sys_init () ;
usb_init () ;
Timer0_Init ();
EA = 1;
LED = 0XFF;
while(1)
{
if(DeviceState !=DEVSTATE_CONFIGURED)
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if(TIM_10MS_Flag==1 )
{
TIM_10MS_Flag=0;
KEY_NUM =MateixKEY_Read();
SEG7 = KEY_NUM;
}
}
3、密码锁编程
密码锁需求:1.通过LEDO模拟门锁状态,LED点亮表示门锁打开,熄灭表示门锁锁上2.增加8位数码管,可以动态
显示8位的密码,无密码时显示“......"3.通过矩阵按键可以输入1-8的数字表示密码,并依次显示在数码管上;4.每
输入一个数字,蜂鸣器响20ms表示有数字按下5.密码正确打开LED0,密码错误蜂鸣响2秒。#include "COMM/stc.h"
#ifndef _ _ KEY_
#define_ _ KEY_
#include"COM/stc.h"
#include"COM/usb.h"
#defineKEY P3 //P32-P35
#defineKEY12//按键1
#defineKEY13//按键2
#defineKEY14//按键3
#defineKEY15//按键4
#defineMateixKEY P0//定义矩阵按键引脚
#define KEY NOPRESS 0 //按键未按下
#define KEY_FILCKER 1 //按键消抖
#define KEY PRESS 2 //单击
#define KEY PRESSOVER3 //单击结束
#define KEY LONGPRESS 4//长按3秒
#define KEY LONGOVER 5//长按结束
#define KEY_RELAX 6//按键松开
密码锁部分程序如下
/*****矩阵按键读取当前是哪一个按钮按下*********/
u8MateixKEY_Read(void)
{
u8 keystate; //表示当前的按键的状态值
u8 key_val = 0; //表示当前按键的键码
//第一步:现将P0.0-P0.3输出低电平◇P0.6-P0.7输出高电平◇如果有按键按下◇
MateixKEY= 0xC0; //1100 0000
MateixKEY_delay();
keystate = ( MateixKEY ^ 0xC0);// 0100 0000 ^1100 0000 =1000 000
//第二步◇现将P0.0-P0.3输出高电平◇P0.6-P0.7输出低电平◇如果有按键按下,按下的那一行IO就会变成低电平。
MateixKEY= OXOf; //0000 1111
MateixKEY_delay();
keystate |=(MateixKEY ^OX0f); //00001110 ^ 00001111 = 0000 0001 | 1000 0000 =0x81。
//第三步:行列组合一下就可以判断出是哪个按键按下了。
printf("0x%02x\r\n",keystate);
switch(keystate)
{
case 0x41: key_val =1;
break;
case 0x42: key_val =2;
break;
case 0x44: key_val =3;
break;
case 0x48: key_val =4;
break;
case 0x81: key_val =5;
break;
case 0x82: key_val =6;
break;
case 0x84: key_val =7;
break;
case 0x88: key_val =8;
break;
default : key_val =0;
break;
}
return keystate;
}
voidmain()
{
u8 KEY_NUM = 0; // 保存矩阵按键的键码
u8 KEY_Str=0;//表示当前输入几个密码位
sys_init () ;
usb_init () ;
Timer0_Init ();
EA = 1;
LED = 0XFF;
while(1)
{
if(DeviceState !=DEVSTATE_CONFIGURED)
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if(TIM_10MS_Flag==1 )
{
TIM_10MS_Flag=0;
KEY_NUM =MateixKEY_Read( );
if(KEY_NUM>0 )
{
BEEP_ON(2); //蜂鸣器2ms
Show_tab = KEY_NUM;
KEY_Str++;
if(KEY_Str ==1)&&(KEY_Str ==2)&&(KEY_Str ==3)&&(KEY_Str ==4)&&(KEY_Str ==5)&&(KEY_Str ==6)&&(KEY_Str ==7)
{
LED0 = 0; //灯亮
}
else
{
BEEN_ON(200) ;//密码错误,蜂鸣器响2秒
}
SEG0=SEG1=SEG2=SEG3=SEG4=SEG5=SEG=6SEG7=21
}
}
KEY_NUM = 0;
}
}
17141200320
发表于 2024-1-9 12:51:42
第15集 外部中断
1、中断系统
中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
当中央处理机 CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,
再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中2、什么是外部中断
外部中断就是在单片机的一个引脚上,由于外部因素导致了一个电平的变化(比如由高变低),而通过捕获这个变化,单片机内部自主运行的
程序就会被暂时打断,转而去执行相应的中断处理程序,执行完后又回到原来中断的地方继续执行原来的程序。
3、外部中断使用方法
4、外部部分程序
voidINT0_Init(void)
{
IT0 = 1;//下降沿中断
EX0 = 1;//允许中断
IE0 = 0;//清除中断标志位
}
voidmain()
{
u8 KEY_NUM = 0;
sys_init () ;
usb_init () ;
Timer0_Init ();
INT0_Init( );
EA = 1;
LED = 0XFF;
while(1)
{
if(DeviceState !=DEVSTATE_CONFIGURED)
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
for(i=0;i<8;i++)
{
LED =(1<<i);
delay_ms(500);
}
if( P33 == 0)
SEG1 +=1;
}
}
void INT0_ Isr (void)interrupt0
{
SEG0+=1;
}
17141200320
发表于 2024-1-10 08:14:29
第16集 IO中断
1、外部中断与IO中断区别
外部中断适用用单此信号,检测信号上升沿或下降沿。
IO口中断适用于持续进入中断信号,检测信号为高电平或低电平,如按键一直按下信号。
2、什么是IO口中断
3、实例-简易中央门禁控制系统
1).用8个按键代表每个门的门锁开关,8个LED作为每个门的工作状态,点亮表示门已经打开,熄灭表示门打开。
2).如遇突发火灾,按下应急按钮立刻打开所有门锁,方便人逃生。
3).按下应急按钮后,所有按钮门锁不能上锁
4).松开应急按钮后,倒计时5秒后恢复之前的状态,并可以操作门锁,
简易中央门禁控制系统部分程序
u16Tme_countDown =0;
voidTime0_init (void) //1毫秒,24MHZ, 12分频
{
AUXR &=0X7F;
TMOD &= 0XF0;
TL0 = 0X30;
TH0 = 0XF8;
TF0 =0;
TR0 = 1;
ET0 = 1;
IP = 0X02; //设置为最高优先集
IPH =0X02;
}
voidP3Exit_Init(void)
{
P3IM0 = 0X00;
P3IM1 = 0XFF; //低电平中断
P3INTE = 0X20;//P35中断00100000
}
voidmain()
{
u8LOCK_State =0xff;//门锁工作状态
u8 KEY_NUM = 0; // 保存矩阵按键的键码
u8 KEY_Str=0;//表示当前输入几个密码位
sys_init () ;
usb_init () ;
Timer0_Init ();
P3Exit_Init();
EA = 1;
LED =LOCK_State ;
while(1)
{
if(DeviceState !=DEVSTATE_CONFIGURED)
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if(TIM_10MS_Flag==1 )
{
TIM_10MS_Flag=0;
if( Tme_countDown ==0)
{
KEY_NUM =MateixKEY_Read( );
BEEP_RUN();
if(KEY_NUM>0 )
{
BEEP_ON(2); //蜂鸣器2ms
LOCK_State^= (1<< KEY_NUM-1)//获取当前第几个按键按下,(1-8)-1
}
LED = LOCK_State;
SEG0 = 20;// 熄灭数码管
}
else
{
Tme_countDown--;
SEG0 = Tme_countDown/100+1; // 500/100 499
}
}
}
}
voidP3Exit)_Isr(void) interrupt 40
{
u8 intf ;
intf = P3INIF ;//读取中断标志位
if( intf)
{
P3INIF =0;
if(intf &0x20) //P35按键按下 0010 0000
{
LED =0X00;//打开所有门锁
SEG0 = 5 ;//数码管持续显示5
Tme_countDown = 500;
}
}
}
17141200320
发表于 2024-1-10 10:45:11
第二集开发板有哪些功能
1、开发板功能有:LED点灯、数码管显示、电压比较、红外发射、红外接收、蜂鸣器、调试接口、RS232电路、FLASH扩展、232接口、USB接口、LED、LCD接口、独立按键、矩阵按键、24C02、DAC、PWM模拟、基准电压、ADC、18B20、
NTC测温。
2、讲了STC32G12K128单片机资源。
17141200320
发表于 2024-1-10 10:55:11
第三集开发环境搭建和程序下载
1、讲了KEIL安装和使用
2、讲了STC_ISP程序下载
17141200320
发表于 2024-1-10 10:55:12
第三集开发环境搭建和程序下载
1、讲了KEIL安装和使用
2、讲了STC_ISP程序下载
17141200320
发表于 2024-1-11 11:07:13
本帖最后由 17141200320 于 2024-1-11 15:15 编辑
第十七集模数转化器ADC
1.模数转换器是什么:
模数转换器即A/D转换器,或简称ADC (Analog-to-、digital converter),通常是指一个将模拟信号转变为数字信号的电子元件。
模拟信号 ->电压.
数字信号 -> 0和1组成的二进制数
利用图形和表格方式描述了AD转化过程
2、ADC查询方式部分程序
#defineADC_CHECK0//查询
#defineADC_Isr 1 //中断
#defineADC_FUNC ADC_Isr // 最终选择
# if ADC_FUNC==ADC_CHECK
voidADC_Init(void) //查询ADCC初始化
{
P1M0 = 0x00;
P1M1 =0X01; //设置P10为高阻输入
ADCTIM = 0X3F;
ADCCFG =0X2F; //数据右对齐,时钟选择sysclk/2/16最慢
ADC_POWER = 1;
}
u16 ADC_Read(u8 no)
{
u16 adcval;
ADC_CONTER &= 0Xf0; //清空通道
ADC_CONTTER|= no; //选择通道
ADC_Start = 1; //开启ADC转化
_nop_(); //空操作指令
_nop_();
while(!ADC_FLAG); //等待ADC转换结束
ADC_FLAG = 0;
adcval = (ADC_RES<<8)+ADC_RESL;
return adcval;
}
u16 ADC_CAL_Voltage(u16 num) //转换电压
{
returnnum*2.5*1000/4096;
}
voidmain()
{
u8 KEY_NUM = 0; //
sys_init () ;
usb_init () ;
Timer0_Init ();
ADC_Init();
EA = 1;
LED = 0XFF;
while(1)
{
if(DeviceState !=DEVSTATE_CONFIGURED)
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if(TIM_10MS_Flag==1 )
{
TIM_10MS_Flag=0;
ADC_VAL = ADC_Read();
Printf ("当前ADC数\xfd值:%d\r\n ",(int)ADC_VAL , (int)ADC_CAL_Voltage(ADC_VAL)); //ad值和相对的电压
}
}
#else if ADC_FUNC==ADC_Isr
voidADC_Init(void) //ADC中断初始化
{
P1M0 = 0x00;
P1M1 =0X01; //设置P10为高阻输入
ADCTIM = 0X3F;
ADCCFG =0X2F; //数据右对齐,时钟选择sysclk/2/16最慢
ADC_POWER = 1;
EADC = 1;
}
voidADC_Isr(void)interrupt5
{
ADC_FLAG = 0;
ADC_VAL= (ADC_RES<<8)+ADC_RESL;
ADC_Start = 1;
}
#else
#endif