第八集:定时器周期性调度任务
笔记:
1、周期性任务介绍
通过任务代码实现过程的讲解,融入了Ai8051U定时器/计数器知识和中断机制的讲解,以及编辑中的技巧、C语言知识点数组和for语句、按键防抖、工具软件的使用等知识点的讲解。
1.1 定义变量实现任务一,用了多个变量分别计数的方法实现一个定时器服务多个任务。
代码如下:
//擎天柱核心板-Ai8051U-32K64,定时器周期性调度任务实验程序。
//任务一,方法一:多个变量分别计数的方法实现一个定时器服务多个任务。
//attach://94320.c
//用到2025年4月8日发布的USB库(CDC):stc_usb_cdc_32g.LIB。
#include "ai8051u.h"
#include "ai_usb.h"
u16 Count_300 = 0;
u16 Count_600 = 0;
u16 Count_900 = 0;
u16 Count_ms = {0, 0, 0};
u8 i;
void Delay20ms(void) //@40.000MHz
{
unsigned long edata i;
_nop_(); _nop_();
i = 199998UL;
while (i--);
}
void Timer0_Isr(void) interrupt 1
{
Count_300++;
Count_600++;
Count_900++;
}
void Timer0_Init(void) //1毫秒@40.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void main(void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR。(32 位模式请使用这句,注释下一句)。
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR。(8 位模式请使用这句,注释上一句)。
WTST = 0; //设置取程序代码等待时间:赋值为0表示不等待,程序以最快速度运行。
CKCON = 0; //设置访问片内的xdata速度:赋值为0表示用最快速度访问,不增加额外的等待时间。
P2M0 = 0x00; P2M1 = 0x00; //设置P2口为准双向口模式。
P3M0 = 0x00; P3M1 = 0x00; //设置P3口为准双向口模式。
usb_init(); //调用USB初始化函数。
Delay20ms();
Timer0_Init(); //调用T0初始化函数。
Delay20ms();
EA = 1; //打开总中断。
{int i = 1; for (i = 1; i <= 300; i++) Delay20ms();} //等待AIapp-ISP下载软件中串口自动打开。
printf_usb("程序开始执行!\r\n");
while (1)
{
//任务一,方法一:多个变量分别计数的方法实现一个定时器服务多个任务。
if (Count_300 >= 300)
{
Count_300 = 0;
P20 = ~P20;
}
if (Count_600 >= 600)
{
Count_600 = 0;
P21 = ~P21;
}
if (Count_900 >= 900)
{
Count_900 = 0;
P22 = ~P22;
}
if(bUsbOutReady) //bUsbOutReady 标志位是用于标明 USB 主机发送完成。
{
USB_SendData(UsbOutBuffer, OutNumber);
printf_usb("\r\n国芯MCU收到数\xfd据:%X\r\n", UsbOutBuffer);
P2 = UsbOutBuffer;
LED40_SetPort(2, P2); //使用AIapp-ISP软件菜单“调试仿真接口”中的“擎天柱-LED-DIP40”进行模拟显示P2口。
usb_OUT_done(); //本包接收的数据处理完毕,准备接收下一包数据。
}
}
}
1.2 定义数组实现任务一,用数组计数的方法实现一个定时器服务多个任务。
代码如下:
//擎天柱核心板-Ai8051U-32K64,定时器周期性调度任务实验程序。
//
//任务一,方法二:数组计数的方法实现一个定时器服务多个任务。
//用到2025年4月8日发布的USB库(CDC):stc_usb_cdc_32g.LIB。
#include "ai8051u.h"
#include "ai_usb.h"
u16 Count_300 = 0;
u16 Count_600 = 0;
u16 Count_900 = 0;
u16 Count_ms = {0, 0, 0};
u8 j;
void Delay20ms(void) //@40.000MHz
{
unsigned long edata i;
_nop_(); _nop_();
i = 199998UL;
while (i--);
}
void Timer0_Isr(void) interrupt 1
{
for (j = 0; j < 3; j++)
{
Count_ms++;
}
if (Count_ms >= 300)
{
P20 = ~P20;
Count_ms = 0;
}
if (Count_ms >= 600)
{
P21 = ~P21;
Count_ms = 0;
}
if (Count_ms >= 900)
{
P22 = ~P22;
Count_ms = 0;
}
}
void Timer0_Init(void) //1毫秒@40.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void main(void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR。(32 位模式请使用这句,注释下一句)。
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR。(8 位模式请使用这句,注释上一句)。
WTST = 0; //设置取程序代码等待时间:赋值为0表示不等待,程序以最快速度运行。
CKCON = 0; //设置访问片内的xdata速度:赋值为0表示用最快速度访问,不增加额外的等待时间。
P2M0 = 0x00; P2M1 = 0x00; //设置P2口为准双向口模式。
P3M0 = 0x00; P3M1 = 0x00; //设置P3口为准双向口模式。
usb_init(); //调用USB初始化函数。
Delay20ms();
Timer0_Init(); //调用T0初始化函数。
Delay20ms();
EA = 1; //打开总中断。
{int i = 1; for (i = 1; i <= 300; i++) Delay20ms();} //等待AIapp-ISP下载软件中串口自动打开。
printf_usb("程序开始执行!\r\n");
while (1)
{
//任务一,方法二:数组计数的方法实现一个定时器服务多个任务。
//此处不需要写代码。
if(bUsbOutReady) //bUsbOutReady 标志位是用于标明 USB 主机发送完成。
{
USB_SendData(UsbOutBuffer, OutNumber);
printf_usb("\r\n国芯MCU收到数\xfd据:%X\r\n", UsbOutBuffer);
P2 = UsbOutBuffer;
LED40_SetPort(2, P2); //使用AIapp-ISP软件菜单“调试仿真接口”中的“擎天柱-LED-DIP40”进行模拟显示P2口。
usb_OUT_done(); //本包接收的数据处理完毕,准备接收下一包数据。
}
}
}
2.3 定义数组实现任务2,有循环数组中存在的值来点亮LED,实现流水灯。
代码如下:
//擎天柱核心板-Ai8051U-32K64,定时器周期性调度任务实验程序。
//
//任务2:数组点亮LED,实现流水灯。
//用到2025年4月8日发布的USB库(CDC):stc_usb_cdc_32g.LIB。
#include "ai8051u.h"
#include "ai_usb.h"
u16 Count_300 = 0;
u16 Count_600 = 0;
u16 Count_900 = 0;
u16 Count_ms = {0, 0, 0};
u8 State = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
u8 i;
u8 num = 0;
void Delay20ms(void) //@40.000MHz
{
unsigned long edata i;
_nop_(); _nop_();
i = 199998UL;
while (i--);
}
void Timer0_Isr(void) interrupt 1
{
for (i = 0; i < 3; i++)
{
Count_ms++;
}
}
void Timer0_Init(void) //1毫秒@40.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void main(void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR。(32 位模式请使用这句,注释下一句)。
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR。(8 位模式请使用这句,注释上一句)。
WTST = 0; //设置取程序代码等待时间:赋值为0表示不等待,程序以最快速度运行。
CKCON = 0; //设置访问片内的xdata速度:赋值为0表示用最快速度访问,不增加额外的等待时间。
P2M0 = 0x00; P2M1 = 0x00; //设置P2口为准双向口模式。
P3M0 = 0x00; P3M1 = 0x00; //设置P3口为准双向口模式。
usb_init(); //调用USB初始化函数。
Delay20ms();
Timer0_Init(); //调用T0初始化函数。
Delay20ms();
EA = 1; //打开总中断。
{int i = 1; for (i = 1; i <= 300; i++) Delay20ms();} //等待AIapp-ISP下载软件中串口自动打开。
printf_usb("程序开始执行!\r\n");
while (1)
{
//任务2:数组点亮LED,实现流水灯。
if (Count_ms >= 500)
{
Count_ms = 0;
P2 = ~State;
num++;
if (num > 7)
{
num = 0;
}
}
if(bUsbOutReady) //bUsbOutReady 标志位是用于标明 USB 主机发送完成。
{
USB_SendData(UsbOutBuffer, OutNumber);
printf_usb("\r\n国芯MCU收到数\xfd据:%X\r\n", UsbOutBuffer);
P2 = UsbOutBuffer;
LED40_SetPort(2, P2); //使用AIapp-ISP软件菜单“调试仿真接口”中的“擎天柱-LED-DIP40”进行模拟显示P2口。
usb_OUT_done(); //本包接收的数据处理完毕,准备接收下一包数据。
}
}
}
2.4 任务3:按键1按一下,LED通过数组移动一下。
用新的实现方式实现了按键防抖,改进了以前方法,堵上一个漏洞。
代码如下:
//擎天柱核心板-Ai8051U-32K64,定时器周期性调度任务实验程序。
//
//任务3:按键按一下,LED通过数组移动一下。
//用到2025年4月8日发布的USB库(CDC):stc_usb_cdc_32g.LIB。
#include "ai8051u.h"
#include "ai_usb.h"
u16 Count_300 = 0;
u16 Count_600 = 0;
u16 Count_900 = 0;
u16 Count_ms = {0, 0, 0};
u8 State = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
u8 i;
u8 num = 0;
u16 Key_Val = 0;
void Delay20ms(void) //@40.000MHz
{
unsigned long edata i;
_nop_(); _nop_();
i = 199998UL;
while (i--);
}
void Timer0_Isr(void) interrupt 1
{
for (i = 0; i < 3; i++)
{
Count_ms++;
}
}
void Timer0_Init(void) //1毫秒@40.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void main(void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR。(32 位模式请使用这句,注释下一句)。
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR。(8 位模式请使用这句,注释上一句)。
WTST = 0; //设置取程序代码等待时间:赋值为0表示不等待,程序以最快速度运行。
CKCON = 0; //设置访问片内的xdata速度:赋值为0表示用最快速度访问,不增加额外的等待时间。
P2M0 = 0x00; P2M1 = 0x00; //设置P2口为准双向口模式。
P3M0 = 0x00; P3M1 = 0x00; //设置P3口为准双向口模式。
usb_init(); //调用USB初始化函数。
Delay20ms();
Timer0_Init(); //调用T0初始化函数。
Delay20ms();
EA = 1; //打开总中断。
{int i = 1; for (i = 1; i <= 300; i++) Delay20ms();} //等待AIapp-ISP下载软件中串口自动打开。
printf_usb("程序开始执行!\r\n");
while (1)
{
//任务3:按键按一下,LED通过数组移动一下。
P2 = ~State;
if (Count_ms >= 1000)
{
Count_ms = 0;
printf_usb("国芯MCU--Ai8051U\r\n");
}
if (Count_ms >= 5)
{
Count_ms = 0;
if (0 == P32) //判断P32按钮是否按下。
{
Key_Val++;
if (5 == Key_Val)
{
num = (num > 7) ? 0 : ++num;
printf_usb("Ai8051U--%d--%d\r\n", num, Key_Val);
}
}
else
{
Key_Val = 0;
}
}
if(bUsbOutReady) //bUsbOutReady 标志位是用于标明 USB 主机发送完成。
{
USB_SendData(UsbOutBuffer, OutNumber);
printf_usb("\r\n国芯MCU收到数\xfd据:%X\r\n", UsbOutBuffer);
P2 = UsbOutBuffer;
LED40_SetPort(2, P2); //使用AIapp-ISP软件菜单“调试仿真接口”中的“擎天柱-LED-DIP40”进行模拟显示P2口。
usb_OUT_done(); //本包接收的数据处理完毕,准备接收下一包数据。
}
}
}
2、文件的创建(.c和.h)
此部分讲解了多文件项目中如何创建新文件并添加到项目中,项目中如何在其它文件中引用别的文件,以及如何将代码拆分归类到不同文件。
2.1 新建新的“.c和.h”后缀的文件,并添加到项目中。两个文件同时建立,名称上只有后缀不同。一般一个.c和一个.h文件归类为执行一个外设或者一个任务或功能。这样可以让代码看起来简洁明了。
2.2 按照如下规则编写.c和.h文件。
新建的xxx.c和xxx.h文件是一组,代表一个功能块。xxx用实际名称全部代换。
(a)xxx.h格式:
#ifndef __XXX_H
#define __XXX_H
调用头文件
函数声明...
#endif
(b)xxx.c格式
#include “xxx.h”
函数定义
添加文件一定要记得引用路径和添加到工程里。
2.3 在项目其它文件的头部引用.h文件。
格式为:
#include "xxx.h"
3、结构体的介绍
结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。
struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:
struct tag {
member-list;
member-list;
member-list;
...
} variable-list;
tag 是结构体标签。
member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。
更多详细信息,请参考网址:https://www.runoob.com/cprogramming/c-structures.html
4、结构体数组的周期性任务调度
4.1 定义结构体,实现任务一,用结构体封装了与定时器有关的成员变量,用来保存对应的数据和函数实现的指向。
定义示例如下:
typedef struct
{
u8 Run; //任务状态:Run/Stop
u16 TIMCount; //定时计数器
u16 TRITime; //重载计数器
void (*TaskHook) (void); //任务函数
} TASK_COMPONENTS;
static TASK_COMPONENTS Task_Comps[] =
{
//状态计数周期函数
{0, 1, 1, 执行功能},
{0, 10, 10,执行功能},
};
4.2 用结构体实现任务一的代码。
代码如下:
attach://94320.c
attach://94317.h
attach://94316.c
attach://94322.h
attach://94321.c
attach://94319.h
attach://94318.c
心得感悟:
通过对周期性任务实现方法的学习,加深了对定时器/计数器功能的理解,同时也加深了对中断机制的理解。
在学习过程中,也学习到了一些代码编辑技巧以及出现问题如何解决的方法。
视频教程中讲解了3个任务,通过对这3个任务的学习,更能体会到条条大路通罗马的感觉,以及积累经验后才能找到相对比较优的路径的感觉,同时不断探索才可能发现新的路径。
总结:
通过学习本期视频,学到如下知识点:
1、定时器/计数器功能和中断机制相结合,能简化代码,提高程序性能,模拟出多任务的“假象”。
2、学习了数组的定义、使用。
3、学习了for循环的使用。
4、学习了在代码中如何注多行。
5、学习了新的按键防抖代码如何编写。
6、学习了项目文件中如何新建和引入.c和.h文件以及编写文件规则。
7、学习了结构体的定义、使用。
后记:
2025年4月16日,开始学习第八集:定时器周期性调度任务。
学习了,厚书读薄{:qiang:} 《8051U深度入门到32位51大型实战教学视频》--学习打卡7
第七集:定时器中断
笔记:
1、定时器的介绍
1.1 定时器逻辑结构。
1.2 定时器/计数器:Ai8051U 系列单片机内部设置了 6 个 24 位定时器/计数器(8 位预分频+16 位计数)。6 个 16 位定时器 T0、T1、T2、T3、T4 和 T11 都具有计数方式和定时方式两种工作方式。
1.3 定时器/计数器0有4种工作模式:模式0(16位自动重装载模式),模式1(16位不可重装载模式),模式2(8位自动重装模式),模式3(不可屏蔽中断的16位自动重装载模式)。定时器/计数器1除模式3外,其它工作模式与定时器/计数器0相同。T1在模式3时无效,停止计数。定时器T2的工作模式固定为16位自动重装载模式。T2可以当定时器使用,也可以当串口的波特率发生器和可编程时钟输出。定时器3、定时器4、定时器11与定时器T2一样,它们的工作模式固定为16位自动重装载模式。T3/T4可以当定时器使用,也可以当串口的波特率发生器和可编程时钟输出。定时器11的工作模式固定为16位自动重装载模式。T11可以当定时器使用,也可编程时钟输出。
1.4 定时器寄存器:TM0PS、AUXR、TMOD、TL0、TH0、TF0、TR0、ET0的设置。
1.5 定时器用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作。
1.6 定时器功能与中断机制结合使用,可替代长时间的延时操作,释放MCU的运算资源,提高程序的运行效率和处理速度(可以打断主循环)。
2、定时器的应用
1.1 任务1:P2口的LED灯三秒取反一次,这期间任意时刻按下按钮P32/INT0,串口打印按键次数。
代码1如下:
//擎天柱核心板-Ai8051U-32K64,时器实验程序。
//任务1:P2口的LED灯三秒取反一次,这期间任意时刻按下按钮P32/INT0,串口打印按键次数。
//
//用到2025年4月8日发布的USB库(CDC):stc_usb_cdc_32g.LIB。
#include "ai8051u.h"
#include "ai_usb.h"
void Delay20ms(void) //@40.000MHz
{
unsigned long edata i;
_nop_(); _nop_();
i = 199998UL;
while (i--);
}
void Timer0_Isr(void) interrupt 1
{
P2 = ~P2;
//LED40_SetPort(2, P2);
}
void Timer0_Init(void) //3秒@40.000MHz
{
TM0PS = 0x98; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void main(void)
{
int count = 0; //按键计数变量
unsigned char dat = 0xff;
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR。(32 位模式请使用这句,注释下一句)。
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR。(8 位模式请使用这句,注释上一句)。
WTST = 0; //设置取程序代码等待时间:赋值为0表示不等待,程序以最快速度运行。
CKCON = 0; //设置访问片内的xdata速度:赋值为0表示用最快速度访问,不增加额外的等待时间。
P2M0 = 0x00; P2M1 = 0x00; //设置P2口为准双向口模式。
P3M0 = 0x00; P3M1 = 0x00; //设置P3口为准双向口模式。
usb_init(); //调用USB初始化函数。
Delay20ms();
Timer0_Init(); //调用T0初始化函数。
Delay20ms();
// IE2 |= 0x80; //使能USB中断。
EA = 1; //打开总中断。
{int i = 1; for (i = 1; i <= 300; i++) Delay20ms();} //等待AIapp-ISP下载软件中串口自动打开。
printf_usb("程序开始执行!\r\n");
P2 = 0xAA;
while (1)
{
if (0 == P32) //判断P32按钮是否按下。
{
Delay20ms(); //延时20ms消抖。
if (0 == P32)
{
printf_usb("按键按下次数\xfd:%d次\r\n", ++count);
while (0 == P32); //等待P32松开。
}
}
if(bUsbOutReady) //bUsbOutReady 标志位是用于标明 USB 主机发送完成。
{
USB_SendData(UsbOutBuffer, OutNumber);
printf_usb("\r\n国芯MCU收到数\xfd据:%X\r\n", UsbOutBuffer);
P2 = UsbOutBuffer;
LED40_SetPort(2, P2); //使用AIapp-ISP软件菜单“调试仿真接口”中的“擎天柱-LED-DIP40”进行模拟显示P2口。
usb_OUT_done(); //本包接收的数据处理完毕,准备接收下一包数据。
}
}
}
1.2 任务2:P2口的LED灯按一下点亮三秒后熄灭。
在任务1代码上修改部分如下:
(a)
void Timer0_Isr(void) interrupt 1
{
P2 = 0xFF;
TR0 = 0; //定时器关闭计时
}
(b)
// Timer0_Init(); //调用T0初始化函数。
(c)
//任务2:灯按一下点亮三秒后熄灭。
if (0 == P32) //判断P32按钮是否按下。
{
Delay20ms(); //延时20ms消抖。
if (0 == P32)
{
P2 = 0x00;
Timer0_Init(); //调用T0初始化函数。
while (0 == P32); //等待P32松开。
}
}
1.3 任务3:救护车灯控制器,按下报警按钮,红蓝交替闪烁(LED1和LED2表示红和蓝灯),再按一下报警按钮,红蓝灯停止。
在任务1代码上修改部分如下:
(a)
void Timer0_Init(void) //500毫秒@40.000MHz
{
TM0PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x99; //设置定时初始值
TH0 = 0x05; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
(b)
void Timer0_Isr(void) interrupt 1
{
P2 = ~P2;
}
(c)
u8 Run_State = 0; //运行状态
(d)
// Timer0_Init(); //调用T0初始化函数。
(e)
//任务3:救护车灯控制器,按下报警按钮,红蓝交替闪烁(LED1和LED2表示红和蓝灯),再按一下报警按钮,红蓝灯停止。
if (0 == P32) //判断P32按钮是否按下。
{
Delay20ms(); //延时20ms消抖。
if (0 == P32)
{
Run_State = !Run_State;
if (1 == Run_State) //运行
{
P2 = 0x0F;
Timer0_Init();
}
else
{
TR0 = 0; //关闭定时器
P2 = 0xFF;
}
while (0 == P32); //等待P32松开。
}
}
3、函数的定义、声明、调用
3.1 函数定义:包含返回值,函数名和入口参数,并定义了函数具体功能。
a. 函数的名称应当能够描述函数的功能,便于代码的阅读和理解。
b. 函数名称应当使用有意义的英文单词或者组合的英文单词,避免使用特殊字符或数字。
c. 函数名称不能与C语言的关键字同名。
返回值类型 函数名(入口参数)
{
// 函数体
// 函数执行的代码
return 返回值;
}
3.2 函数声明:在头文件中或者被调用之前使用,注意末尾要加分号。
返回值类型 函数名(入口参数);
3.3 函数调用:在需要调用的地方直接使用函数名,加上括号和分号。如果有入口参数的,需要在括号的多个参数之间加逗号隔开。
函数名(入口参数);
学习心得:
1、此集视频虽然内容不多,但是定时器/计数器很基础,基于MCU的核心功能加法器,基于中断,在时间维度上巧妙地解决了MCU实现多任务的方法。
2、此集看过多遍,了解了定时器/计数器的逻辑结构以及设置步骤。
3、学习了设置定时器/计数器时用到的寄存器的功能、作用。
4、掌握了利用AIapp-ISP下载软件中生成代码的技巧;掌握在芯片手册中由端口到寄存器,再到设置寄存器每一位的方法。
5、此集在讲解知识点时也并行地介绍了一些代码编辑的技巧和方法,对提高编程效率有帮助。
总结:
1、此集看过多遍,在陆陆续续整理思路,我心里清楚我对MCU的理解又深了一层。
2、比较清晰地掌握了定时器/计数器的逻辑结构、功能、设置、使用方法,更高级的使用后续要继续学习与研究。
3、初步掌握了中断的知识。
4、通过3个实例代码的编写、修改,发现初学者往往困在知识经验少上,积累需要时间。有一本通俗易懂、简洁全面的好芯片手册很重要。
后记:
修修改改终于写完此集笔记。
2025年4月16日。
《8051U深度入门到32位51大型实战教学视频》--学习打卡6
第六集:IO输入输出
笔记:
1、什么是GPIO
1.1 GPIO(General Purpose I/O Ports)是通用输入/输出端口,是一些芯片引脚,可以通过它们输出高低电平或者读入引脚的状态(是高电平或是低电平)。
1.2 实践中高电平是指接近于芯片电源正极电压(Vcc)的电平,也叫逻辑“1”;低电平就是接近芯片GND电压(0V)的电平,也叫逻辑“0”。
1.3 GPIO的工作模式有4种。
1.4 芯片上电时默认施密特触发模式是打开的,可以在程序中设置端口寄存器的值为“0”来关闭。在Vdd=3.3V时,高电平为大于1.18V(打开)或1.09V(关闭),低电平为低于0.99V(打开)或1.07V(关闭)。
2、按键输入检测
2.1 按键是接在MCU的端口上的,端口状态可在端口对应的寄存器中读写。读取按键的状态就是读取按键的对应IO口的电平,也就是读取端口寄存器的状态。
2.2 因为机械按键按下或者松开有抖动,一般在20ms内。按键抖动的出现会影响程序的正常执行。代码中要加入按键防抖处理。
2.3 利用AIapp-ISP下载软件中的“软件延时计算器”功能生成延时函数代码,用于按键防抖处理。
3、课后小练
3.1 任务1:按一下P32按钮灯亮,按一下P33按钮灯灭。
3.2 任务2:按一下亮一颗灯,在按一下亮两颗灯,直到全亮(变量+加法和乘法)
感受:
1、实现端口功能时要先设置端口状态。
2、要了解接口电路才能理解代码为什么这样编写。
3、编码出现问题时要仔细检查端口设置,仔细看芯片手册。
总结:
1、学习了端口的硬件和端口寄存器的对应,端口如何表示不同状态。
2、初步学习了端口的4中工作模式。
3、学习了如何读写端口状态。
4、学习了一种按键防抖的技术。
《8051U深度入门到32位51大型实战教学视频》--学习打卡5
第五集:C语言基础
笔记:
1、C语言USB-CDC串口之printf函数的实现
1.1 USB-CDC串口将标准C语言中的printf进行了扩展。
1.2 复习标准printf的参数用法。
int printf(const char *fmt, ...),
参数fmt:是格式控制字符串,包含了两种类型的对象:普通字符和转换说明 。
普通字符:在输出时,普通字符将原样不动地复制到标准输出。
转换说明:不直接输出,用于控制printf中参数的转换和打印。
每个转换说明都由一个百分号字符(%)开始,以转换说明符结束,从而说明输出数据的类型、宽度、精度等。
转换说明简介:
a. 类型:根据不同的fmt字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了fmt参数中指定的每个%标签。关于附加参数,既可以是变量,也可以是常量。
b. 位置:printf()函数的普通字符和转换说明放在双引号内(""),附加参数放在双引号外,每个附加参数之间用逗号隔开。
c. 数量:printf()函数的附加参数与转换说明符是⼀⼀对应关系,如果有n个转换说明符,printf()的参数就应该有n+1个。如果参数个数少于对应的转换说明符,printf()可能会输出内存中的任意值。
更详细的可参考这里:https://c.biancheng.net/view/ublxqif.html。
1.4 ASCII码表
更详细的可以参考这里:https://www.jyshare.com/front-end/6318/。
1.5 复习define的用法。
2、数的进制:2进制、10进制、16进制
更详细的可以参考这里:https://cloud.tencent.com/developer/article/2148978。
3、数据的基本类型
更详细的可以参考这里:https://www.runoob.com/cprogramming/c-data-types.html。
还有这里:https://cloud.tencent.com/developer/article/2207965。
4、C语言常用运算符
更详细的可以参考这里:https://www.runoob.com/cprogramming/c-operators.html。
感悟:
C语言的基本知识还需要再复习。要多练习记得才清楚。
总结:
1、复习了printf()的使用方法。
2、复习了ASCII码表。
3、复习了二、十、十六进制。
4、复习了C语言的六类运算及对应的运算符。
C语言还有其它的很多内容没复习到,在开发过程中随时学习。
《8051U深度入门到32位51大型实战教学视频》--学习打卡4
第四集:USB不停电下载
笔记:
1、实验对比演示
1.1 视频演示的技术很方便下载程序。
2、下载所需文件
2.1 在STC官网(https://www.stcai.com/khs)-->软件工具-->库函数中找到USB库文件的下载地址并下载必要文件。
2.2 解压开USB库文件。
3、移植关键USB库文件到工程
3.1 将USB功能对应模式(CDC或HID模式)的头文件(例如:ai_usb.h)和库文件(例如:stc_usb_cdc_32g.LIB)复制到已有工程目录中来。
3.2 在Keil开发软件中将新复制过来的库文件加入工程中来。
3.3 在工程源代码文件main.c的头部添加“#include "ai_usb.h"”,引入头文件。
3.4 参考芯片手册和示例中代码,在源代码文件中添加寄存器设置、USB初始化函数以及其它功能代码。寄存器设置详情参考芯片手册。
3.5 编译源代码生成MCU运行程序文件。
4、设置AIapp-ISP下载软件参数
4.1 在AIapp-ISP下载软件中按照图示设置“硬件选项”选项页的参数。
4.2 在AIapp-ISP下载软件中按照图示设置“收到用户命令后复位到ISP监控程序区”选项页的参数。
5、下载程序到MCU并验证不停电下载
5.1 按照以前正常手动下载程序步骤将新运行程序下载到MCU中。
5.2 修改源代码并编译成新的运行文件后观察AIapp-ISP下载软件是否能自动下载新的运行程序。
感悟:
这个USB不停电下载很方便,编译成功后的步骤自动完成,节约了时间,使开发轻松了一些。
要修改代码才能实现,不知以后能否不用修改代码就能实现。
总结:
1、学习了引入库文件。
2、学习了如何迁移软件。
3、学习了芯片手册的查询。
4、学习了USB不停电下载技术实现步骤。
《8051U深度入门到32位51大型实战教学视频》--学习打卡3
第三集:点亮第一个LED
笔记:
1、新建工程
1.1 在Keil uVision程序菜单中依次选择“Project”-->“New uVision Project...”,在随后弹出的窗口中先选择好文件保存的目录然后输入文件名,之后按“保存”按钮即可。
1.2 在菜单中依次选择“Project”-->“Options for target ‘Target 1’”,在弹出的窗口中选择好参数,之后按“”按钮即可。主要是在“Device”选项卡中:选择 STC MCU Database,选择“Ai8051U-32Bit Series”选项;在“Target”选项卡中:Memory Model 选择 XSmall 模式以及勾选 4 字节对齐选项;在“Output”选项卡中:勾选 Create HEX File,选择 HEX-80。
2、添加头文件
2.1 打开AIapp-ISP编程下载软件,然后在软件右边功能区的“Keil仿真设置”选项卡中用鼠标点击“添加型号和头文件到Keil中 添加仿真器驱动到Keil中”按钮。
2.2 在弹出窗口中选择Keil软件安装的目录即可。
注:头文件也可以在AIapp-ISP编程下载软件中的“头文件”选项卡中手工生成,然后手工拷贝到项目所在目录中。在代码中引用头文件时用双引号将头文件全名引起来。
3、添加代码文件
3.1 在Project窗口区内用鼠标右键点击“Source Group1”,于弹出的右键快捷菜单中选中“Add New Item to Group ‘Source Group 1’”。
3.2 在弹出窗口中选择“Type”(文件类型)是:*.c,在“Name”输入框中输入文件名是:main 或其他任意文件名,在“Location”输入框中选择当前项目的目录,然后点击“Add”按钮,将该新文件加入到当前项目。
4、打开main.c文件并编写文件
4.1 在Keil开发软件中打开main.c文件。
4.2 在文件编辑区输入MCU的C语言代码。
4.3 编辑完成后,在开发软件菜单中依次选择“File”-->“Save”,将文件保存。
5、编译源程序
5.1 在Keil开发软件菜单中依次选择“Project”-->“Build Target”,执行编译过程。
注:如果编译无错误,会在项目目录下的“.\Object”目录中生成后缀是“.hex”的可执行程序文件。如果编译出错误,返回上面第4个步骤修改代码。
6、将可执行程序下载到MCU中
以下部分以擎天柱核心板为例。
6.1 打开AIapp-ISP编程下载软件,并选择芯片型号:AI8051U-32K64,选择CPU指令模式:32-Bit。
6.2 用USB线将擎天柱核心板与开发电脑连接。
6.3 在核心板上先按住“P32 INT0”按钮不放,然后点按“POWER”按钮,然后松开“P32 INT0”按钮。此时AIapp-ISP软件中的串口扫描处会显示:(HID1)USB-Writer。
6.4 在AIapp-ISP软件中按下“下载/编程”按钮,执行程序下载,下载完成后,会在信息显示区显示“操作成功 !”。
注:如果成功,核心板上已经下载好新程序并开始执行。否则,请检查本节步骤重新下载。
感悟:
步骤按照教学视频不难,代码如果严格按照视频中内容的也很容易。
对于C语言不熟悉的人难点在C语言的基础内容上。
想实现一些类似的代码,往往卡在C语言上,要花很多时间上网搜索、学习。
另外,芯片手册很重要,要尽可能尽快熟悉它。
总结:
通过本集教学视频的学习,学到了开发一个MCU程序并在MCU中运行起来的全过程。
主要包括:新建工程,添加必要头文件,添加并编写源代码文件,编译源代码,下载程序到MCU。
新建工程时要注意工程路径名中不要出现汉字,文件命名中也不要出现汉字。
程序编译过程中常常出现的问题是头文件没有找到或用了错误的头文件。
代码编写时注意细节和规范。
芯片手册很重要,编写代码过程中要多参考。
《8051U深度入门到32位51大型实战教学视频》--学习打卡2
第二集:硬件及工具介绍
笔记:
1、硬件介绍
实验箱挺漂亮。
PCB板正面:
1.1 几种USB口。
1.2 TF卡插座。
1.3 示波器BNC输入口。
1.4 2种立体声输出口。
1.5 话筒录音。
1.6 OLED、SPI、I2C接口。
1.7 8位流水灯。
1.8 8位数码管。
1.9 TFT彩屏。
1.10 掉电检测电压调节。
1.11 红外接收和发射。
1.12 矩阵键盘。
1.13 Ai8051U。
1.14 ADC键盘。
1.15 T0、T1按键。
1.16 INT0、INT1按键。
1.17 复位按键。
1.18 电源按键。
1.19 QSPI/SPI Flash。
1.20 外部并行总线扩展32K SRAM。
1.21 LCD对比度调节。
1.22 RTC电池。
PCB板背面:
1.23 32768Hz无源晶振。
1.24 24C02 EEPROM。
1.25 DS18B20温度传感器。
1.26 无源蜂鸣器。
1.27 SP3485 485通信芯片。
1.28 AI8H2K12U USB转双串口芯片。
1.29 TP2604S、74HC4051、LMV358、TLV320AIC23B等芯片。
2、软件和工具
2.1 下载、安装Keil编程软件。
群中找找,或者找技术支持。
注意设置好安装路径并记好。
自己去参考编译环境搭建去文档设置。
2.2 下载、安装AIapp-ISP软件。
STC官方网站下载。
2.3 下载、添加头文件。
STC官方网站下载。
在AIapp-ISP软件中,为Keil软件添加型号和头文件,添加仿真器驱动。
2.4 下载、添加插件。
STC官方网站下载。
在下载的插件软件中,为Keil软件添加插件。例如中断插件。
2.5 下载代码包和手册。
STC官方网站下载。
3、下载第一个程序
3.1 使用USB线将实验箱与电脑进行连接。
3.2 打开AIapp-ISP软件。
3.3 选择单片机型号为“AI8051U-34K64”,打开需要下载的用户程序。
3.4 实验箱使用硬件USB接口下载。
进入USB下载模式需要先按住实验箱上的P3.2/INT0按键(P3.2口接地),然后按下ON/OFF电源按键或者断电,接着松开ON/OFF电源按键或者上电,最后松开P3.2/INT0按键(P3.2口断开接地)。
正常情况下就能识别出“(HID1)USB-Writer”设备。
3.5 点击AIapp-ISP软件中的“下载/编程”按钮。
特别注意:
下载示例程序时,要到源程序中查看芯片时钟频率,向MCU中下载程序时要在AIapp-ISP软件中选对“用户程序运行时的IRC频率”。
感悟:
注意好细节,按照步骤,一步一步操作,应该电灯程序不难下载成功。
总结:
1、学习了试验箱硬件组成。
2、学习了软件环境的搭建。这一部分步骤稍微复杂,仔细理解各部分的功能和关系,才能将它们有机地结合成一个顺畅的开发环境。
3、学习下载到MCU上一个示例程序。这一步要看好步骤,细心操作。
《8051U深度入门到32位51大型实战教学视频》--学习打卡1
第一集:序言
笔记:
哪怕为梦想拼的遍体鳞伤,也要勇往直前!(对视频中的一句话自己的理解和改写)
了解信息或遇到问题,可用如下方式联系以获得信息
STC官网:https://www.stcai.com/
STC论坛:https://www.stcaimcu.com/
分销商电话:0513-55012928 / 89896509 / 55012929 / 55012966
1、Ai8051U强在哪里?
1.1 屏幕显示和视频播放(Flash编程器)--优化了QSPI的Flash芯片读写,显示色彩丰富,刷新帧率高,中英文和图片显示效果好。用8080并口,做图形菜单效果好。视频文件用Flash编程器刷入选定的芯片。
1.2 IIS录放音--做全了。可替代以前的录放音模块。
1.3 PWM_DMA--能很好兼容了。可实现1000多颗2812灯互不干扰。
1.4 频谱分析仪(上位机)--有了硬件浮点乘除单元可实现。实现了FFT的快速数据刷新。
1.5 手写计算--可结合AI的技术。
1.6 QSPI、PWM移相、硬件乘除、单精度浮点--实现的最新功能。
2、Ai8051U简介
2.1 Ai8051U,USB型 1T 8051,支持32位和8位指令集。
2.2 管脚兼容天王级别芯片:89C52RC,12C5A60S2。
2.3 在兼容8位8051指令集时,可以用Keil C51/IAR/SDCC编译器,芯片就相当于更强大的8H8K64U芯片。
2.4 在兼容32位8051指令集时,可以用Keil C251编译器,双核兼容设计,芯片就相当于更强大的32G12K128,32G8K64芯片。
2.5 34K SRAM(2K edata,32K xdata),64K Flash。
2.6 TFPU@120MHz,硬件浮点/硬件三角函数运算器。
2.7 DMA支持PWM,DMA支持外设直接到外设,P2P。
2.8 120MHz-PWM支持硬件移相,16位PWM。
2.9 USB,4组串口,真12位ADC,轨到轨比较器。
2.10 QSPI,SPI,I2S,I2C,TFT-i8080/M6800接口。
2.11 PDIP40,LQFP44,LQFP48。
2.12 RMB2.3。
感悟:
8051系列后续的发展与超越在国芯这里实现了。可喜可贺!
中华文明与智慧几千年的沉淀使我们有很强的方向感,中华民族的精神与品质使我们不会停下追逐梦想的脚步。
这第一集很简单。 学习Ai8051U的总结笔记
背景介绍
作为一名对电子技术充满兴趣的爱好者,我对单片机的基础知识已有一定了解。8位的51系列单片机在嵌入式系统中应用广泛,然而,在深圳国芯人工智能公司推出的支持32位/8位51指令集的MCU——Ai8051U,让我看到了新的技术突破。这款MCU不仅在运算能力上表现出色,还具备丰富的接口和卓越的性能,非常适合用于开发智能化仪表等测量设备。
Ai8051U的特点
1. 指令集兼容性:Ai8051U支持32位和8位的51指令集,这意味着开发者可以充分利用现有的51系列代码资源,同时享受32位处理器的强大性能。
2. 高性能运算:相较于传统的8位51单片机,Ai8051U在运算速度和处理能力上有了显著提升,能够满足更复杂的应用需求。
3. 丰富的接口:Ai8051U提供了多种接口选项,包括UART、SPI、I2C等,便于与各种外设进行通信,扩展了其应用范围。
4. 低功耗设计:在保证高性能的同时,Ai8051U还注重低功耗设计,适合用于电池供电的便携式设备。
学习过程
1. 注册论坛会员:为了更好地学习Ai8051U,我首先注册了深圳国芯人工智能公司的论坛会员,获取了相关的学习资源和技术支持。
2. 观看教学视频:按照《8051U深度入门到32位51大型实战视频》的课程安排,我系统地学习了Ai8051U的硬件架构、指令集、开发环境搭建以及实际应用案例。
3. 实践操作:在学习过程中,我通过实际操作,熟悉了Ai8051U的开发工具和编程环境,逐步掌握了其编程技巧和调试方法。
学习心得
1. 技术突破:Ai8051U的出现,不仅延续了51系列单片机的经典,更在性能上实现了质的飞跃,为嵌入式系统开发提供了更多可能性。
2. 学习资源丰富:深圳国芯人工智能公司提供的教学视频和论坛资源,为学习者提供了全面的技术支持,极大地降低了学习门槛。
3. 实践重要性:通过实际操作,我深刻体会到理论与实践相结合的重要性,只有通过不断的实践,才能真正掌握Ai8051U的应用技巧。
未来展望
在未来的学习中,我计划进一步深入研究Ai8051U的高级功能,如DMA、定时器、中断处理等,以期在智能化仪表的开发中发挥其最大潜力。同时,我也期待深圳国芯人工智能公司能够推出更多创新的MCU产品,推动嵌入式技术的发展。
结语
Ai8051U作为一款支持32位/8位51指令集的MCU,不仅在性能上超越了传统的51系列单片机,更为嵌入式系统开发带来了新的机遇。通过系统的学习和实践,我对Ai8051U有了更深入的理解,也对其在智能化仪表等领域的应用充满信心。期待在未来的项目中,能够充分发挥Ai8051U的强大功能,实现更多创新应用。
[本文内容由国芯人工智能辅助生成,仅供参考]
页:
1
[2]