|
发表于 2023-7-18 12:12:10
|
显示全部楼层
开始学习
第一集
了解什么是单片机,如何学习单片机。
第二集
了解实验箱上所有元器件以及其功能。
第三集
开发环境搭建完成,坐等开发板。
第四集 点亮LED
LED一端连接电阻接P6口,另一端接三极管外接高,当P6,P4口输出低电平,三极管导通,LED相当于一端接高一端接地,此时LED点亮。编写代码用的是寄存器,习惯了使用库函数对于寄存器的使用不太习惯。特殊功能寄存器sfr,sbit定义特殊功能寄存器的位变量。使用端口数据寄存器P4、P6,模式配置寄存器P4M0、P4M1、P6M0、P6M1都设置为0(准双向口),将定义好位变量P40、P60附值为0点亮LED,然后学习如何实现不断电下载程序的功能,在<stc32g.h>包含寄存器定义,无需自己定义。
第五集
C语言基础知识基本都学过
要实现printf需要添加如下代码
if( DeviceState != DEVSTATE_CONFIGURED)
continue;
if(bUsbOutReady){
usb_OUT_done();
printf();
}
每次打印信息都要加上这些代码,还需要使用串口发送数据才能接收数据,有没有别的方法实现printf。
第六集
控制LED灯闪烁,需P60先给低电平,延时后再给高电平。延时用到了delay_ms函数,函数里用到了while和do.....while循环,代码能够看懂,但是为什么这么写能够实现ms延时不清楚。在学习如何实现LED闪烁中间穿插了C语言知识,比如#define用法,a--和--a区别,while和do.....while区别,函数使用,模块化编程,这样方式让我对C语言理解更加透彻。
第七集
因为开关是机械开关,所以按下松开时需要进行按键消抖。
正常LED不亮,按下按键,LED从左往右流水
#define KEY1 P32
u8 LED_State[8] = {0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F};
void main()
{
u8 num = 0;
P6 = 0xFF;
if(KEY1 == 0)
{
delay_ms(10);
if(KEY1 == 0)
{
P6 = LED_State[7-num];
delay_ms(500);
num++;
if(num > 7) num = 0;
}
}
}
第八集
P54给低电平,蜂鸣器工作。使用一个电磁炉实际应用将之前所学LED,按键和蜂鸣器进行整合,巩固所学知识,知道所学是如何应用于实际生活中的。
第九集
数码管由多个发光二极管组成,点亮数码管和点亮LED一样。由发光二极管组成不同形状,点亮不同二极管就可以显示不同图案,比如显示数字0~9。
练习显示
H:0x89 J:0xf1 L:0xc7 n:0xab o:0xa3
P:0x8c U:0xe3 t:0x87 r:0xaf
KEY1控制数码管显示0~9循环,KEY2根据数字控制蜂鸣器鸣叫
u8 SEG[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
P6 = SEG[num];
if(KEY1 == 0)
{
delay_ms(10);
if(KEY1 == 0)
{
while(KEY1 == 0);
if(num < 9)num++;
if(num == 9)num = 0;
}
}
if(KEY2 == 0)
{
delay_ms(10);
if(KEY2 == 0)
{
while(KEY2 == 0);
while(num--)
{
BEEP = 0;
delay_ms(50);
BEEP = 1;
}
}
}
第十集
数码管动态刷新就是依次让每个数码管显示图案,虽然依次点亮数码管中间有延迟时间,但是由于人眼分辨率原因,多个数码管循环时间不超过20ms的情况下,在人眼看来数码管是一直显示的,这样就实现了多个数码管的动态显示。
练习
u8 hour = 0;
u8 minute = 0;
u8 second = 0;
u8 SEG[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
u8 COM[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
u8 SHOW[8] = {hour/10,hour%10,10,minute/10,minute%10,10,second/10,second%10};
void SEG_Fre(void)
{
P7 = COM[num];
P6 = SEG[SHOW[num]];
delay_ms(1);
num++;
if(num > 7)num=0;
}
void main()
{
num = 0;
SEG_Fre();
while(1)
{
P6 = SEG[SHOW[num]];
delay_ms(1000);
second++;
if(second > 59){
minute++;
second = 0;
}
if(minute > 59){
hour++;
minute = 0;
}
if(hour > 23){
hour = 0;
}
if(hour == 0 && minute == 0 && second == 30)
{
beep = 1;
delay(3000);
beep = 0;
}
}
}
第十一集
定时器具有计数和定时两种工作方式,定时本质就是对脉冲进行计数,不同定时器通过操作不同寄存器来设置定时还是计数功能,比如T0和T1操作TMOD寄存器。定时器模式下可以设置分频,此时定时器每12个时钟或者每1个时钟得到一个计数脉冲,计数值加一。定时器/计数器0有4种工作模式,可通过TMOD寄存器的T0_M1/T0_M0设置。IE中的EA是中断总开关,ET0为定时器0的中断允许位。使用定时器比延时更加高效和精确。计算定时时间手算比较慢,还容易出错,可以通过官方提供工具,选择好时钟,定时时间,模式,自动计算并生成代码,大大提高效率。
第十二集
定时器要设置为计数功能,需要配置TMOD的C/T为1
计数器根据脉冲来计数,在模式1下,计数最大值为65536,超过65535就会产生中断,设置预装载值TH0/TL0,当计数溢出时,重载为预装载值。
第十三集
学习使用模块化编程,每个外设单独一个.c/.h文件。在写函数时,为函数添加一些注释性内容,方便他人阅读。
使用extern 修饰符用来说明变量和函数在别的地方已经定义,需要在此处引用。extern修饰变量不能赋初值。
学习使用bdata位寻址变量。
第十四集
了解矩阵按键,使用矩阵按键可以减少IO口占用。按键数量x*y,IO口数量需要x+y
控制列IO口输出低电平,行IO口输出高电平,当按键按下,可以知道哪一行按键按下;
控制列IO口输出高电平,行IO口输出低电平,当按键按下,可以知道哪一列按键按下;
行列一组合就能知道哪个按键被按下。
第十五集
在主程序运行过程中,有中断请求时,需要进行响应去执行中断处理程序,执行完后再返回主程序继续执行。
CPU总是先响应优先级最高的中断请求,然后按照优先级高低顺序来依次执行中断服务程序。
外部中断是捕获单片机上引脚电平变化,单片机上只有一些固定引脚才能被用作外部中断的IO口。
|
|