打卡学习《Ai8051U深度入门大型实战视频》
第一集:讲解了8051U的新功能
突出介绍了Ai8051U的强大功能
第二集
讲解了Ai8051U实验箱硬件和软件开发工具
软件下载工具
第三集 点亮第一颗LED
从本讲开始要写实际的代码了。
相对来说,代码比较简单,容易理解,有C语言基础就行。
#include "ai8051u.h" //调用头文件
void main(void)
{
P2M0 = 0; //P2端口(P20-P27)为准双向口
P2M1 = 0;
while(1)
{
P20 = 0; //P20端口输出0V
P27 = 0; //P27端口输出0V
}
}
第四集 USB不停电下载
上一讲中的代码下载,需要反复按电源键和p3.2按键才能正常下载。
本讲实现了开发板不停电下载,免去了反复按键的麻烦,非常实用。提高了开发效率。
要实现这个功能,就需要调用官方提供的usb库。要将这个库加入项目中。
上代码:
#include "ai8051u.h"
#include "stc32_stc8_usb.h" //新增调用USB头文件
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void main(void)
{
P_SW2 |= 0x80; // B7位写1,使能访问XFR
// ...
usb_init(); // 初始化 USB CDC 接口配置
IE2 |= 0x80; // 使能USB中断
EA = 1; // IE |= 0X80;
while (DeviceState != DEVSTATE_CONFIGURED)
; // 等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
usb_OUT_done();
}
P20 = 0; // P00端口输出0V
P22 = 0; // P02端口输出0V
}
}
第五集 C语言基础
使用STC-USB库实现的printf函数,可以直接与上位机通信,方便调试及与单片机交互。
代码:
#include "ai8051u.h" //调用头文件
#include "stc32_stc8_usb.h" //调用头文件
#define u8 unsigned char // 8位无符号变量(0-255)
#define u16 unsigned int // 16位无符号变量(0-65535)
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void main(void)
{
P_SW2 |= 0x80; // B7位写1,使能访问XFR
// ...
usb_init(); // USB CDC 接口配置
IE2 |= 0x80; // 使能USB中断
EA = 1; // IE |= 0X80;
while (DeviceState != DEVSTATE_CONFIGURED)
; // 等待USB完成配置
while (1)
{
if (bUsbOutReady) // 如果接收到了数据
{
printf("向上位机发送的信息\r\n"); // 发送消息给上位机
usb_OUT_done();
}
}
}
第六集 I/O输入输出
本集简要介绍了GPIO,高电平、低电平的概念。
并通过将按键接入IO端口进行了讲解。最后用3个小任务,以实例的形式介绍了通过检测按键,控制led的亮和灭。
上代码:
#include "ai8051u.h" //调用头文件
#include "stc32_stc8_usb.h" //调用头文件
#include "intrins.h" //d调用头文件
#define u8 unsigned char // 8位无符号变量(0-255)
#define u16 unsigned int // 16位无符号变量(0-65535)
u8 state = 0; // 初始状态
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void Delay20ms(void) //@24.000MHzDelay20ms();
{
unsigned long edata i;
_nop_();
_nop_();
i = 119998UL;
while (i)
i--;
}
void main(void)
{
WTST = 0;// 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; // 扩展寄存器(XFR)访问使能
CKCON = 0; // 提高访问XRAM速度
// ...
usb_init(); // USB CDC 接口配置
IE2 |= 0x80; // 使能USB中断
EA = 1; // IE |= 0X80;
P40 = 0;
while (DeviceState != DEVSTATE_CONFIGURED)
; // 等待USB完成配置
while (1)
{
if (bUsbOutReady) // 如果接收到了数据
{
usb_OUT_done(); //
}
// 任务1:按下P32按钮灯亮,松开P32按钮灯灭;
if (P32 == 0) // 判断P32按钮是否按下
{
P00 = 0;
}
else
{
P00 = 1;
}
// 任务2:按下P32按钮灯灭,松开P32按钮灯亮;
if (P32 == 1) // 判断P32按钮是否按下
{
P00 = 0;
}
else
{
P00 = 1;
}
// 任务3:按一下灯亮,按一下灯灭
if (P32 == 0) // 判断P32按钮是否按下
{
Delay20ms(); // 延时20ms消抖
if (P32 == 0)
{
state = !state; // 变量取反 0 1 0 1 0 1
P00 = state;
printf("state:%d\r\n", (int)state);
while (P32 == 0)
; // 等待P32松开
}
}
}
}
第七集 定时器
在本集中,冲哥给我们讲解的单片机的重要部件之一:定时器。那什么是定时器,能干什么?翻阅数据手册:
Ai8051U 系列单片机内部设置了 6 个 24 位定时器/计数器(8 位预分频+16 位计数)。6 个 16 位定时器 T0、T1、T2、T3、T4 和 T11 都具有计数方式和定时方式两种工作方式。
定时器/计数器 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 可以当定时器使用,也可编程时钟输出。
在实际项目中,STC-ISP工具给我们提供了一个便捷工具,帮助我们快速计算定时数据:
①:在下载软件中选择“定时器计算器”功能页,进定时器代码生成界面
②:设置系统工作频率(单位:MHz)
③:设置定时时间长度(单位:毫秒/微秒)
④:选择目标定时器,并设置定时器工作模式
⑤:选择是否需要使能定时器中断
⑥:手动生成 C 代码或者 ASM 代码,复制范例
最后,通过3个小任务给出了具体应用实例:
// 任务1:
if (P32 == 0) // 判断P32按钮是否按下
{
Delay20ms(); // 延时20ms消抖
if (P32 == 0)
{
printf("按键按下次数\xfd:%d 次\r\n", (int)count);
count++;
while (P32 == 0)
; // 等待P32松开
}
}
// 任务2:灯按一下点亮三秒后熄灭。
if (P32 == 0) // 判断P32按钮是否按下
{
Delay20ms(); // 延时20ms消抖
if (P32 == 0)
{
printf("按键按下次数\xfd:%d 次\r\n", (int)count);
count++;
P00 = 0;
Timer0_Init();
while (P32 == 0)
; // 等待P32松开
}
}
// 任务3:救护车灯控制器,按下报警按钮,红蓝交替闪烁(LED1和LED2表示红和蓝灯),再按一下报警按钮,红蓝灯停止。
if (P32 == 0) // 判断P32按钮是否按下
{
Delay20ms(); // 延时20ms消抖
if (P32 == 0)
{
Run_State = !Run_State; // 运行状态取反
if (Run_State == 1) // 运行
{
Timer0_Init();
}
else
{
TR0 = 0; // 关闭定时器
P00 = 1;
P01 = 1;
}
while (P32 == 0)
; // 等待P32松开
}
}
第八集 周期性调度任务
本集接续上一集,用定时器来实现周期性的任务调度,避免了用循环方法,释放单片机资源,提高系统响应速度,改善用户体验。
通过实现三个任务,冲哥深入浅出地讲解了如何用定时器来周期性地调度这些任务:
任务1:用一个定时器实现这个任务。LED1实现0.3秒取反一次,LED2实现0.6秒取反一次,LED3 0.9秒取反一次
任务2:数组点亮LED,实现流水灯
任务3:按键按一下,LED通过数组移动一下;
在代码实现中,通过数组的方式来定义任务:
static TASK_COMPONENTS Task_Comps[] = {
// 状态计数周期函数
{0, 300, 300, LED0_Blink}, /* task 1 Period: 300ms */
{0, 600, 600, LED1_Blink}, /* task 1 Period: 600ms */
{0, 900, 900, LED2_Blink}, /* task 1 Period: 600ms */
{0, 10, 10, KEY_Task}, /* task 1 Period: 600ms */
};
任务回调处理代码:
u8 Tasks_Max = sizeof(Task_Comps) / sizeof(Task_Comps);
void Task_Pro_Handler_Callback(void)
{
u8 i;
for (i = 0; i < Tasks_Max; i++)
{
if (Task_Comps.Run) /* If task can be run */
{
Task_Comps.Run = 0; /* Flag clear 0 */
Task_Comps.TaskHook(); /* Run task */
}
}
}
第九集 数码管
本集讲解了
1.数码管介绍
2.数码管显示原理
3.数码管静态显示
4.数码管动态显示
5.虚拟显示——LED和数码管
八段数码管由8个发光二极管构成,通过不同的组合可用来显示数字0~9、字符A~F和小数点“.”。分为共阳极和共阴极两种结构。
如果静态显示8位数码管,至少需要占用8*8+3位IO端口,非常浪费宝贵的端口资源。
在实际的项目中,多采用动态显示模式。利用人眼的视觉暂留原理,逐位动态扫描显示,可以达到多位视觉上同时显示的效果。
在实际的实现中,还需要注意消隐,改善视觉效果。
代码:
void Send_595(u8 dat)
{
u8 i;
for (i = 0; i < 8; i++)
{
dat <<= 1; // DAT = (DAT<<1); //CY
HC595_SER = CY; // 先把数据写到引脚上
HC595_SCK = 1; // 输出上升沿的时钟信号
HC595_SCK = 0;
}
}
void Display_Seg(u8 HC595_1, u8 HC595_2)
{
Send_595(HC595_1); // 数码管段码输出高电平点亮
Send_595(HC595_2); // 数码管位码 低电平点亮
HC595_RCK = 1; // 数据输出
HC595_RCK = 0;
}
void Seg_Task(void)
{
u8 num = 0;
if (Seg_no == 0) // 小时十位
{
num = shi / 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 1) // 小时的个位
{
num = shi % 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 2) // 第一个横杠
{
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 3) // 分钟的十位
{
num = fen / 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 4)
{
num = fen % 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 5)
{
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 6)
{
num = miao / 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 7)
{
num = miao % 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else
{
}
Seg_no++;
if (Seg_no > 7)
Seg_no = 0;
}
<h2>第十集 虚拟LED数码管</h2>
<p>手上只有擎天柱的朋友有福了!AIAPP-ISP提供了虚拟功能!</p>
<p>先准备好三件套:</p>
<p><img src="data/attachment/forum/202502/03/164342i3nszautsmviamwn.png" alt="图片1.png" title="图片1.png" /></p>
<p>isp提供的虚拟功能为快速调试提供了便利条件。</p>
<ol>
<li>虚拟显示——LED</li>
</ol>
<p><img src="data/attachment/forum/202502/03/165016xi86nvrvlzi6tngr.png" alt="11.PNG" title="11.PNG" /></p>
<p>2 虚拟显示——数码管</p>
<p><img src="data/attachment/forum/202502/03/165027waqga2qlql0sa2hr.png" alt="22.PNG" title="22.PNG" /></p>
<p>3 虚拟键盘</p>
<p><img src="data/attachment/forum/202502/03/165052h1k1kktx2epn6vkp.png" alt="33.PNG" title="33.PNG" /></p>
页:
[1]
2