AI8051U学习打卡(一)
<h1>AI8051U学习打卡(一)</h1><h1>1. <strong>AI8051U硬件资源</strong></h1>
<p><strong>Ai8051U-LQFP48 比普通 M0/M3,比 32F103C8T6 强太多的地方:</strong></p>
<ol>
<li>**Ai8051U有TFPU@120MHz, 算力比他强, uS级硬件三角函数/浮点运算器; **</li>
<li><strong>Ai8051U的抗干扰比他强;</strong></li>
<li><strong>Ai8051U的内部复位是专业级的复位电路,彻底省外部复位;</strong></li>
<li>**Ai8051U的内部时钟完全满足串口通信要求,4组串口; **</li>
<li>**Ai8051U-LQFP48有 QSPI, i8080/M6800-TFT 接口,32F103C8T6没有; **</li>
<li><strong>Ai8051U的PWM支持硬件移相@120MHz ;</strong></li>
<li><strong>Ai8051U是 34K SRAM ;</strong></li>
<li><strong>Ai8051U是 自带硬件USB, 1个芯片就能直接USB连接电脑仿真/下载,</strong></li>
<li><strong>全球唯一 ===这个开发生态,全球最强 Ai8051U-LQFP48, RMB2.3含税</strong></li>
</ol>
<p><img src="data/attachment/forum/202412/16/100001xzczqna8a80gdzaq.jpg" alt="" /></p>
<h1>2. <strong>开发环境搭建</strong></h1>
<p><strong>官网下载地址:</strong><a href="https://www.stcai.com/cp_ai8051uxl">深圳国芯人工智能有限公司-产品_AI8051U系列</a></p>
<p><strong>必备资料清单:</strong></p>
<p><img src="data/attachment/forum/202412/16/100000hihflk4xlxodxiai.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100000z0ueu9qj0oje6zac.jpg" alt="" /></p>
<h2>2.1. <strong>keil-C251软件设置</strong></h2>
<p><img src="data/attachment/forum/202412/16/100000kj6jqlm6kast96ej.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100000ddbibdv11b5vdrlz.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100001h7nw2brf1gz152g1.jpg" alt="" /></p>
<h1>AI8051U学习打卡(二)</h1>
<h2><strong>2.1点灯实验</strong></h2>
<p><img src="data/attachment/forum/202412/16/100155lr7xx8100v4lx697.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100155lhj0d4zhjjrjsk44.jpg" alt="" /></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "stdio.h"
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#define MAIN_Fosc 24000000UL
//==========================================================================
/*************本地常量声明 **************/
/*************IO口定义 **************/
/*************本地变量声明 **************/
/*************本地函数声明 **************/
voiddelay_ms(u8 ms);
/****************外部函数声明和外部变量声明 *****************/
/******************** 主函数 **************************/
void main(void)
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P40 = 0; //LED Power On
while(1)
{
P00 = 0; //LED On
delay_ms(250);
P00 = 1; //LED Off
P01 = 0; //LED On
delay_ms(250);
P01 = 1; //LED Off
P02 = 0; //LED On
delay_ms(250);
P02 = 1; //LED Off
P03 = 0; //LED On
delay_ms(250);
P03 = 1; //LED Off
P04 = 0; //LED On
delay_ms(250);
P04 = 1; //LED Off
P05 = 0; //LED On
delay_ms(250);
P05 = 1; //LED Off
P06 = 0; //LED On
delay_ms(250);
P06 = 1; //LED Off
P07 = 0; //LED On
delay_ms(250);
P07 = 1; //LED Off
}
}
//========================================================================
// 函数: voiddelay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
voiddelay_ms(u8 ms)
{
u16 i;
do{
i = MAIN_Fosc / 6000;
while(--i);
}while(--ms);
}
</code></pre>
<h2>2.2. <strong>STC-link下载</strong></h2>
<p><strong>打开一个点灯程序,按如下配置成功烧录,成功点亮led。</strong></p>
<p><strong>下面那个复位引脚作io也不要勾选,不然复位按键失效。</strong></p>
<p><img src="data/attachment/forum/202412/16/100155t6rv1jzhiw818htz.jpg" alt="" /></p>
<h2>实物演示:</h2>
<p><img src="data/attachment/forum/202412/16/101232odz1bz2bfc2sbgc1.gif" alt="e94c643a0dc57bd1f0f6de2820d8de22.gif" title="e94c643a0dc57bd1f0f6de2820d8de22.gif" /></p>
<h1>AI8051U学习打卡(三)</h1>
<h1>3. <strong>USB不停电下载(usb-cdc-uart)</strong></h1>
<p><img src="data/attachment/forum/202412/16/100350sn1lmjt661l15o6v.jpg" alt="" /></p>
<p><strong>没下载不停电下载程序之前,还是之前的流水灯代码,这个时候直接只用一根usb线连接电脑是没有任何反应的。</strong></p>
<p><strong>图方便就用那个STC-link来下载。插上STC-link之后就显示出来串口了,如图所示。</strong></p>
<p><img src="data/attachment/forum/202412/16/100350ib8exltqhadyduhi.jpg" alt="" /></p>
<p><strong>然后和上一节一样正常直接烧录下面的代码就行。</strong></p>
<p><img src="data/attachment/forum/202412/16/100350zmdnrfdqmogjgxrw.jpg" alt="" /></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
/******************** 主函数 **************************/
void main(void)
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
}
}
</code></pre>
<p><strong>不用STC-link,再次只用一个usb线连接电脑,发现识别到一个新的串口,这个是usb虚拟串口,支持任意波特率。</strong></p>
<p><img src="data/attachment/forum/202412/16/100350errgbjl2qbmj2nlx.jpg" alt="" /></p>
<p><strong>之后就可以直接用这个不断电下载程序了,也不用STC-link了,但是代码框架不能改,如果重新烧录之前流水灯的代码,就会又识别不到了,又只能用STC-link或者断电下载了。</strong></p>
<p><img src="data/attachment/forum/202412/16/101420qrz055khsw0i52wd.png" alt="image.png" title="image.png" /></p>
<h2>3.1. <strong>printf打印</strong></h2>
<p><img src="data/attachment/forum/202412/16/100615t3wfd2o8666aa8sn.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100615eog1wj3orl34y8r2.jpg" alt="" /><img src="data/attachment/forum/202412/16/100615tg7ez92jexi96o9j.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100615jnuf1u963mm0jiz7.jpg" alt="" /></p>
<h1>AI8051U学习打卡(四)</h1>
<h1>4. <strong>GPIO输入输出</strong></h1>
<p><img src="data/attachment/forum/202412/16/100952zulguuc7cxdvgzg4.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100952ehtt6nvrwpdt55dr.jpg" alt="" /></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
uint8_t led_state = 0;
/******************** 主函数 **************************/
void main(void)
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
if(P32 == 0)//判断按键按下
{
Delay20ms();//按键消抖
if(P32 == 0)
{
led_state ^=1;
P00 = led_state;
printf("led_state:%d\r\n",led_state);
while(P32 == 0); //等待按键松开
}
}
}
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/113404u1vpz5vp9v3pq1i1.jpg" alt="" /><img src="data/attachment/forum/202412/16/113404a99zvbvz6nsxs0zp.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/113404zuroq4gg8un8q4ff.jpg" alt="" /></p>
<h1>AI8051U学习打卡(五)</h1>
<h1>5. <strong>定时器中断</strong></h1>
<h2>5.1. <strong>定时器资源</strong></h2>
<p><img src="data/attachment/forum/202412/16/112219eeacihq9s4777p37.jpg" alt="" /></p>
<h2>5.2. <strong>软件配置定时器</strong></h2>
<p><img src="data/attachment/forum/202412/16/112220irjfot0tzf0rwy43.jpg" alt="" /></p>
<p><strong>下载代码之后led成功每隔3秒亮灭一次,然后串口也能打印按下次数。</strong></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
void Timer0_Init(void) //3秒@40MHz
{
TM0PS = 0x98; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
uint8_t led_state = 0;
/******************** 主函数 **************************/
void main(void)
{
uint8_t cnt = 0;
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
if(P32 == 0)//判断按键按下
{
Delay20ms();//按键消抖
if(P32 == 0)
{
cnt++;
printf("按键按下次数\xfd:%d\r\n",cnt);
while(P32 == 0); //等待按键松开
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
led_state ^=1;
P00 = led_state;
}
</code></pre>
<h2>5.3. <strong>bug解决</strong></h2>
<h3>5.3.1. <strong>keil警告</strong></h3>
<p><img src="data/attachment/forum/202412/16/112220hfyv98gga38gg8uu.jpg" alt="" /></p>
<h3>5.3.2. <strong>串口打印乱码</strong></h3>
<p><img src="data/attachment/forum/202412/16/112219m3eme65zcysg1156.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/112220w35xel2ql77z2vl0.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/112220d79i76n6ff9zl9y6.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/112220p8ch97s9r77v7bgc.jpg" alt="" /></p>
<h2>5.4. <strong>定时器时间计算</strong></h2>
<p><img src="data/attachment/forum/202412/16/112221g5uzb8u0cuu0afjz.jpg" alt="" /></p>
<p><strong>TM0PS:分频系数(psc)</strong></p>
<p><strong>(65536-):目标计数值(arr)</strong></p>
<p><strong>Sysclk:系统时钟(40Mhz)</strong></p>
<p><strong>eg:</strong></p>
<p><img src="data/attachment/forum/202412/16/112220skct4xplukt2zrr8.jpg" alt="" /></p>
<p><strong>TM0PS = 152</strong></p>
<p><strong> = 177</strong></p>
<p><strong>(152+1)*(65536 - 177)*12/40000000 = 2.9999781s</strong></p>
<h3>5.4.1. <strong>定时器0延时3s关灯</strong></h3>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
void Timer0_Init(void) //3秒@40MHz
{
TM0PS = 0x98; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
uint8_t led_state = 0;
/******************** 主函数 **************************/
void main(void)
{
// uint8_t cnt = 0;
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
// Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
//任务1
// if(P32 == 0)//判断按键按下
// {
// Delay20ms();//按键消抖
// if(P32 == 0)
// {
// cnt++;
// printf("按键按下次数\xfd:%d\r\n",cnt);
// while(P32 == 0); //等待按键松开
// }
// }
//任务2
if(P32 == 0)//判断按键按下
{
Delay20ms();//按键消抖
if(P32 == 0)
{
P00 = 0;//开灯
Timer0_Init(); //定时器0初始化
printf("定时器开启,灯亮\r\n");
while(P32 == 0); //等待按键松开
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
// led_state ^=1;
// P00 = led_state;
P00 = 1;//关灯
TR0 = 0;//关闭定时器
printf("定时器关闭,灯灭\r\n");
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/112220yjyjj1s15j591vej.jpg" alt="" /><img src="https://www.stcaimcu.com/data/attachment/forum/202412/16/112313xjsmmxf7d9ns6993.gif" alt="8b4b4b6f89bb99854d2d3afd28eec964.gif" title="8b4b4b6f89bb99854d2d3afd28eec964.gif" /></p>
<h3>5.4.2. <strong>灯交替闪烁</strong></h3>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
//void Timer0_Init(void) //3秒@40MHz
//{
// TM0PS = 0x98; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
// AUXR &= 0x7F; //定时器时钟12T模式
// TMOD &= 0xF0; //设置定时器模式
// TL0 = 0xB1; //设置定时初始值
// TH0 = 0x00; //设置定时初始值
// TF0 = 0; //清除TF0标志
// TR0 = 1; //定时器0开始计时
// ET0 = 1; //使能定时器0中断
//}
void Timer0_Init(void) //500毫秒@40MHz
{
TM0PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x99; //设置定时初始值
TH0 = 0x05; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
uint8_t led_state = 0;
uint8_t run_state = 0;
/******************** 主函数 **************************/
void main(void)
{
// uint8_t cnt = 0;
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
// Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
//任务1
// if(P32 == 0)//判断按键按下
// {
// Delay20ms();//按键消抖
// if(P32 == 0)
// {
// cnt++;
// printf("按键按下次数\xfd:%d\r\n",cnt);
// while(P32 == 0); //等待按键松开
// }
// }
//任务2
// if(P32 == 0)//判断按键按下
// {
// Delay20ms();//按键消抖
// if(P32 == 0)
// {
// P00 = 0;//开灯
// Timer0_Init(); //定时器0初始化
// printf("定时器开启,灯亮\r\n");
// while(P32 == 0); //等待按键松开
// }
// }
//任务3
if(P32 == 0)//判断按键按下
{
Delay20ms();//按键消抖
if(P32 == 0)
{
run_state ^= 1;
if(run_state == 1)
{
Timer0_Init(); //定时器0初始化
printf("定时器开启,灯开始闪\r\n");
}
else
{
P00 = 1;//关灯
P01 = 1;//关灯
TR0 = 0;
printf("定时器关闭,灯停止闪\r\n");
}
while(P32 == 0); //等待按键松开
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
// led_state ^=1;
// P00 = led_state;
// P00 = 1;//关灯
// TR0 = 0;//关闭定时器
// printf("定时器关闭,灯灭\r\n");
led_state ^=1;
P00 = led_state;
P01 = !led_state;
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/112221pxjjij672v7jo9a3.jpg" alt="" /><img src="data/attachment/forum/202412/16/112221v6ohgp6v60zdgxdv.jpg" alt="" /></p>
<p>贴主的笔记很详细,给你点个赞<img alt="qiang" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/qiang.gif" title="qiang" /></p>
<p>希望你能继续坚持下去</p>
<h1>AI8051U学习打卡(六)</h1>
<h1>6. <strong>定时器任务调度</strong></h1>
<h2>6.1. <strong>任务1:</strong></h2>
<p><strong>用一个定时器实现这个任务。LED1实现0.3秒取反一次,LED2实现0.6</strong></p>
<p><strong>秒取反一次,LED3实现0.9秒取反一次。</strong></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
uint16_t Timer0_cnt ={0,0,0};//定时器0任务周期时间数组
uint8_t i;
void Timer0_Init(void) //1毫秒@40MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
uint8_t led1_state = 0;
uint8_t led2_state = 0;
uint8_t led3_state = 0;
uint8_t run_state = 0;
/******************** 主函数 **************************/
void main(void)
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
//任务1
if(Timer0_cnt >= 300)
{
Timer0_cnt = 0;
led1_state ^= 1;
P00 = led1_state;
}
if(Timer0_cnt >= 600)
{
Timer0_cnt = 0;
led2_state ^= 1;
P01 = led2_state;
}
if(Timer0_cnt >= 900)
{
Timer0_cnt = 0;
led3_state ^= 1;
P02 = led3_state;
}
}
}
void Timer0_Isr(void) interrupt 1
{
for(i=0;i<3;i++)
{
Timer0_cnt++;
}
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300e9qz36y01thp1lc8.jpg" alt="" /></p>
<h2>6.2. <strong>任务2:</strong></h2>
<p><strong>数组点亮LED,实现流水灯。</strong></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
/*
b0 b1 b7
低 高
LED0 —— LED7
0 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1
1 1 0 1 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 0 1 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 0
*/
uint8_t LED_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint16_t Timer0_cnt ={0,0,0};//定时器0任务周期时间数组
uint8_t i;
void Timer0_Init(void) //1毫秒@40MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
/******************** 主函数 **************************/
void main(void)
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
//任务2
if(Timer0_cnt >= 500)
{
Timer0_cnt = 0;
P0 = ~LED_State;
if(++LED_pos >= 8) LED_pos = 0;
}
}
}
void Timer0_Isr(void) interrupt 1
{
for(i=0;i<3;i++)
{
Timer0_cnt++;
}
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300xfirf7rzs1zhrj79.jpg" alt="" /></p>
<h2>6.3. <strong>任务3:</strong></h2>
<p><strong>按键按下一次,LED通过数组移动一下。搭配定时器扫描消抖,不阻塞串口发送,串口稳定1s发一次。</strong></p>
<pre><code class="language-c">#include "../COMM/AI8051U.h"
#include "../COMM/usb.h"
#include "stdio.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
//==========================================================================
void Delay20ms(void) //@40MHz
{
unsigned long edata i;
_nop_();
_nop_();
i = 199998UL;
while (i) i--;
}
/*
b0 b1 b7
低 高
LED0 —— LED7
0 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1
1 1 0 1 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 0 1 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 0
*/
uint8_t LED_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint16_t Timer0_cnt ={0,0,0};//定时器0任务周期时间数组
uint8_t i;
uint8_t KEY_press = 0;//按键扫描消抖变量
void Timer0_Init(void) //1毫秒@40MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFB; //设置定时初始值
TH0 = 0xF2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
/******************** 主函数 **************************/
void main(void)
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P00 = 0; //LED Power On
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
//任务3
P0 = ~LED_State;
if(Timer0_cnt >= 1000)
{
Timer0_cnt = 0;
printf("HELLO_AI8051U\r\n");
}
if(Timer0_cnt >= 10)
{
Timer0_cnt = 0;
if(P32 == 0)
{
KEY_press++;
if(KEY_press >= 10)
{
KEY_press = 0;
if(++LED_pos >= 8) LED_pos = 0;
}
}
else
{
KEY_press = 0;
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
for(i=0;i<3;i++)
{
Timer0_cnt++;
}
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300dxyy778x8js7w788.jpg" alt="" /><img src="data/attachment/forum/202412/16/160300q0nhbj9sibynz9ys.jpg" alt="" /></p>
<p><strong>工程中文文件名报错,修改为英文即可。</strong></p>
<p><img src="data/attachment/forum/202412/16/160300exj6q7b76murpqxq.jpg" alt="" /></p>
<h2>6.4. <strong>任务四:</strong></h2>
<p><strong>任务四是在任务一的基础上加了基于定时器0实现的多任务系统架构,使得代码更加简洁高效。</strong></p>
<pre><code class="language-c">#include "system.h"
#include "task.h"
/*
b0 b1 b7
低 高
LED0 —— LED7
0 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1
1 1 0 1 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 0 1 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 0
*/
uint8_t LED_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint8_t i;
/******************** 主函数 **************************/
void main(void)
{
System_Init();
usb_init(); //USB CDC 接口配置
IE2 |= 0X80; //开启USB中断
Timer0_Init(); //定时器0初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while (1)
{
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("hello mikeybie\r\n");
usb_OUT_done();
}
Task_Callback_Handler();
}
}
void Timer0_Isr(void) interrupt 1
{
Task_Run_Time();
}
</code></pre>
<pre><code class="language-c">#include "task.h"
#include "gpio.h"
Task_Struct My_Task[]=
{
{0,10,10,KEY_Task},
{0,300,300,LED0_Blink},
{0,600,600,LED1_Blink},
{0,900,900,LED2_Blink},
};
uint8_t Task_Max = sizeof(My_Task)/sizeof(My_Task);
//任务状态标记函数,放在定时器1ms中断函数里面
void Task_Run_Time(void)
{
uint8_t i;
for(i=0;i<Task_Max;i++)//扫描每一个任务列表
{
if(My_Task.tim_cnt)//任务执行周期有值
{
My_Task.tim_cnt--;
if(My_Task.tim_cnt == 0)//任务执行周期到了
{
My_Task.tim_cnt = My_Task.tim_newcnt;//重新赋值周期
My_Task.task_state = 1;//标记任务可执行状态
}
}
}
}
//任务回调函数处理
void Task_Callback_Handler(void)
{
uint8_t i;
for(i=0;i<Task_Max;i++)
{
if(My_Task.task_state)
{
My_Task.task_state = 0;
My_Task.task_callback();
}
}
}
</code></pre>
<pre><code class="language-c">#include "gpio.h"
uint8_t led0_state=0;
uint8_t led1_state=0;
uint8_t led2_state=0;
uint8_t KEY_press = 0;//按键扫描消抖变量
void LED0_Blink(void)
{
led0_state ^= 1;
P00 = led0_state;
}
void LED1_Blink(void)
{
led1_state ^= 1;
P01 = led1_state;
}
void LED2_Blink(void)
{
led2_state ^= 1;
P02 = led2_state;
}
void KEY_Task(void)
{
if(P32 == 0)
{
KEY_press++;
if(KEY_press >= 10)
{
KEY_press = 0;
printf("按键按下\r\n");
}
}
else
{
KEY_press = 0;
}
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300t0opookyxzxy5zy8.jpg" alt="" /><img src="data/attachment/forum/202412/16/160300ybozbroommzjspdl.jpg" alt="" /></p>
272761180 发表于 2024-12-16 12:29
贴主的笔记很详细,给你点个赞
希望你能继续坚持下去
谢谢 KeilC251安装完,安装包按钮灰色啥原因 wamcncn 发表于 2024-12-16 16:30
KeilC251安装完,安装包按钮灰色啥原因
?截图看看
页:
[1]
2