定时器中断 | 集中在这个帖子打卡
学习了第七集定时器中断,效果很好,加上自己修改、综合了其他程序加入,也成功实现了,在之前没解决的问题也解决了,对于新手小白非常友好!还得是8051u!#include <AI8051U.H>
#include "led.h"
#include "ai_usb.h"
#include "timer.h"
//LED变量
unsigned char ucLed = 0x01; //0000 0001
//Timer变量
unsigned int xms = 0;
unsigned int Led_Dly = 0;
//function
void Led_Proc(void);
void main(void)
{
EAXFR = 1; //
WTST = 0; //
CKCON = 0; //
P0M0 = 0x00; P0M1 = 0x00; //
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
Timer0_Init();
usb_init();
EA = 1;
while(1)
{
if(bUsbOutReady)
{
usb_OUT_done();
}
Led_Proc();
}
}
void Timer0_Isr(void) interrupt 1
{
xms++;
Led_Dly++;
Led_Display(ucLed);
}
void Led_Proc(void)
{
if(Led_Dly < 500)return;
Led_Dly = 0;
ucLed = _crol_(ucLed,1); //zuoyi 1 wei
}
#include <AI8051U.H> //AI8051U的通用头文件,头文件不分大小写
#include "ai_usb.h" //USB库的头文件,头文件不分大小写
/*
如何获得上面这2个头文件,如已按照前面介绍的方法:
从www.STCAI.com 网站,【软件工具 | 工具软件】处,下载安装最新的【AIapp-ISP 软件】,
选择其中的选项卡 【Keil仿真设置 】,
点击【添加型号和头文件到Keil中,并添加仿真器驱动到Keil中】按钮,
则 Ai8051U.h 和 AI_usb.h 都会自动复制到Keil 中, 包含进来就可以直接使用,
大家可以打开看下其中的内容,AI_usb.h 和 stc32_stc8_usb.h是相似的,只需用其中的1个头文件,
具体见 Keil_v5\C251\INC\STC 目录,或 Keil_v5\C51\INC\STC 目录。
如将对应的 USB库文件添加到 项目中,后续用户程序中,USB如收到命令字符串 "@STCISP#"
USB库函数就会自动软复位到系统ISP程序区,实现 USB不停电下载,具体见相应部分的说明。
//char *USER_DEVICEDESC = NULL;
//char *USER_PRODUCTDESC = NULL;
//char *USER_STCISPCMD = "@STCISP#";
//使用20250319之前版本的库函数时需要在用户代码中增加上面3行定义。
//使用20250319及以后的版本都不再需要上面的定义
*/
bit t0_flag = 0; //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询到该定时器已产生中断,在主循环中处理定时器0的中断任务,不堵塞其他中断
bit t1_flag = 0; //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询到该定时器已产生中断,在主循环中处理定时器1的中断任务,不堵塞其他中断
void Timer0_Isr(void) interrupt TMR0_VECTOR //定时器0中断服务程序
{
P00 = ~P00; //P00灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
t0_flag = 1; //置1,记录定时器0已产生中断,供主循环判断要处理定时器0的中断任务
}
//定时器0中断服务程序,TMR0_VECTOR在AI8051U.H头文件中已宏定义为1
void Timer0_Init(void) //定时器0初始化,2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
voidTimer1_Isr(void)interruptTMR1_VECTOR
{
P07 = ~P07; //P07灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
t1_flag = 1; //置1,记录定时器1已产生中断,供主循环判断要处理定时器1的中断任务
}
//定时器1中断服务程序,TMR1_VECTOR在AI8051U.H头文件中已宏定义为3
void Timer1_Init(void) //定时器1初始化,500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
voidsys_init(void) //系统初始化
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
}
voidmain(void)
{
sys_init(); //调用系统初始化函数
usb_init(); //调用USB初始化函数,不需要立即判断电脑已正确识别到USB从设备
/* USB型单片机从设备,如需要主动向电脑发送数据,
在执行USB_SendData( )函数和printf_usb( )函数时,
这两个函数已增加了判断电脑是否已正确识别到USB从设备的程序。
如果电脑要主动发送数据给USB从设备,电脑自己会主动判断与USB从设备是否已正确连接。
*/
EA = 1; //使能中断
Timer0_Init(); //调用定时器0初始化函数
Timer1_Init(); //调用定时器1初始化函数
P40 = 0; //给LED灯供电
while(1) //主循环中查询需要处理的各种事件,如T0/T1中断事件,并打印输出状态
{
if(t0_flag) //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0; //清0,T0事件位变量标志
printf_usb("Timer0!\r\n");
}
if(t1_flag) //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
{
t1_flag = 0; //清0,T1事件位变量标志
printf_usb("Timer1!\r\n");
}
}
}
要 做到 USB不停电下载;
要 尝试 AiCube 图形化自动配置生成程序工具;
推荐优先看的:
printf_usb("Hello World !\r\n")及
USB不停电下载, 演示视频链接:
https://www.stcaimcu.com/thread-19077-1-1.html
下载 最新的 AiCube-ISP-V6.96L 或以上版本软件 !
深圳国芯人工智能有限公司-工具软件
下载 最新的 USB库函数,永远用最新的 USB库函数 !
深圳国芯人工智能有限公司-库函数
下载 最新的 用户手册 !
下载 最新的 上机实践指导书 !
下载 最新的 Ai8051U 用户手册
https://www.stcaimcu.com/data/download/Datasheet/AI8051U.pdf
下载 最新的 Ai8051U 实验指导书,
有 AiCube 图形化自动配置生成程序工具使用说明
https://www.stcaimcu.com/data/do ... %AF%BC%E4%B9%A6.pdf
https://v.stcai.com/sv/1c5eec2-197fcd9b766/1c5eec2-197fcd9b766.mp4
上面是 小李 演示:Ai8051U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
楼主 USB程序,不是我们最优化后的程序 感谢 www.STCAI.com 的支持 !利用注册获得Ai8051U芯片 !以下是简单的的实验程序,效果非常好!
#include "ai8051u.h"
#include "ai_usb.h"
#define MAIN_Fosc 40000000ul
unsigned char n;
unsigned char ucLed = 0x01;
void delay(unsigned int xms)
{
用ai8051u核心功能板实现了简单流水灯的程序实现,非常棒!#include "ai8051u.h"
#include "ai_usb.h"
#define MAIN_Fosc 40000000ul
unsigned char n;
unsigned char ucLed = 0x01;
void delay(unsigned int xms)
{ unsigned int i;
do{
i = MAIN_Fosc / 6000;
while(i--);
}while(xms--);
}
void main(void)
{
EAXFR = 1;
WTST = 0;
CKCON = 0;
P2M0 = 0x00;
P2M1 = 0x00;
usb_init();
EA = 1;
P2 = 0x01; //1111 1110
while(1)
{
if(bUsbOutReady)
{
usb_OUT_done();
}
for(n = 0; n < 8; n++)
{
ucLed = 1 << n;
P2 = ~ucLed;
delay(500);
}
}
学习了时钟和按键的结合,利用按键可以调整时钟的时、分、秒,结果太棒了!
#include <AI8051U.H>
#include "ai_usb.h"
#include "seg.h"
#include "timer.h"
#include "key.h"
unsigned int xms = 0; // 毫秒计时变量
unsigned char Seg_String; // 显示字符串缓存(预留小数点/结束符)
unsigned char Seg_Code = {0,0,0,0,0,0,0,0}; // 数码管段码数组
unsigned char pos = 0; // 数码管扫描位置
unsigned int Seg_Dly = 0; // 显示刷新延时
unsigned char Key_Value; // 按键扫描值
unsigned char Key_Old,Key_Down; // 按键状态(旧值/下降沿)
unsigned char Key_Dly = 0; // 按键消抖延时
unsigned char Seg_Mode = 0; // 显示模式:0-正常时钟 1-调时 2-调分 3-调秒
// RTC时间变量
unsigned char hour = 22;
unsigned char min = 42;
unsigned char sec = 00;
void Seg_Proc(void);
void Key_Proc(void);
void RTC_Proc(void);
void main(void)
{
EAXFR = 1;
WTST = 0;
CKCON = 0;
// 所有端口设为推挽输出(根据硬件调整)
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
Timer0_Init();
usb_init();
EA = 1;
while(1)
{
RTC_Proc();
Seg_Proc();
Key_Proc();
}
}
void Seg_Proc(void)
{
if(Seg_Dly < 500) return;
Seg_Dly = 0;
// 根据显示模式切换显示内容
switch(Seg_Mode)
{
case 0: // 正常运行:显示时分秒(格式:HH:MM:SS)
sprintf(Seg_String,"%02d-%02d-%02d", (int)hour, (int)min, (int)sec);
break;
case 1: // 调时模式:仅显示小时(闪烁/高亮,此处简化)
sprintf(Seg_String,"%02d ", (int)hour);
break;
case 2: // 调分模式:仅显示分钟
sprintf(Seg_String," %02d", (int)min);
break;
case 3: // 调秒模式:仅显示秒
sprintf(Seg_String," %02d", (int)sec);
break;
}
Seg_Trans(Seg_String, Seg_Code);
}
void Key_Proc(void)
{
if(Key_Dly < 20) return; // 按键消抖(20ms)
Key_Dly = 0;
// 按键扫描:下降沿检测
Key_Value = Key_Du_Read();
Key_Down = Key_Value & (Key_Old ^ Key_Value); // 仅捕获按键按下的下降沿
Key_Old = Key_Value;
switch(Key_Down)
{
case 2: // 模式切换键:0→1→2→3→0
Seg_Mode++;
if(Seg_Mode == 4) Seg_Mode = 0;
break;
case 3: // P33按键:调小时(仅在调时模式/正常模式下生效)
if(Seg_Mode == 0 || Seg_Mode == 1)
{
hour++;
if(hour >= 24) hour = 0; // 24小时制循环
}
break;
case 4: // P34按键:调分钟(仅在调分模式/正常模式下生效)
if(Seg_Mode == 0 || Seg_Mode == 2)
{
min++;
if(min >= 60) min = 0; // 分钟0-59循环
}
break;
case 5: // P35按键:调秒(仅在调秒模式/正常模式下生效)
if(Seg_Mode == 0 || Seg_Mode == 3)
{
sec++;
if(sec >= 60) sec = 0; // 秒0-59循环
}
break;
default:
break;
}
}
void Timer0_Isr(void) interrupt 1
{
xms++;
Seg_Dly++;
Key_Dly++;
// 数码管动态扫描
Seg_Disp(Seg_Code, pos);
if(++pos == 8) pos = 0;
}
void RTC_Proc(void)
{
if(xms == 1000) // 1秒计时
{
xms = 0;
if(++sec == 60) // 秒满60进1分
{
sec = 0;
if(++min == 60) // 分满60进1小时
{
min = 0;
if(++hour == 24) // 小时满24重置
{
hour = 0; // 修复原代码未重置hour的BUG
}
}
}
}
}
刚刚学习了流水灯+led的知识,完成代码的编写、修改和输出,最后利用ai8051u核心功能板显示输出,感觉非常不错!
#include <AI8051U.H>// ==================== 硬件配置宏定义 ====================#define LED_PORT P1 // LED控制端口(P10-P17)#define LED_ON0 // 共阴极LED:0=亮,1=灭;共阳极则改为1#define LED_OFF 1// 按键引脚位掩码(P3口)- 替代P3_2/P3_3等位定义#define KEY1_MASK 0x04 // P32 = 第2位(0000 0100)#define KEY2_MASK 0x08 // P33 = 第3位(0000 1000)#define KEY3_MASK 0x10 // P34 = 第4位(0001 0000)#define KEY4_MASK 0x20 // P35 = 第5位(0010 0000)// ==================== 全局变量定义 ====================unsigned char led_mode = 1; // 模式:1=流水灯 2=单独LED 3=全亮/全灭unsigned char flow_dir = 0; // 流水灯方向:0=左→右 1=右→左unsigned char flow_pos = 0; // 流水灯当前位置(0-7)unsigned char single_led = 0; // 模式2下当前点亮的LED位bit all_led_state = 0; // 模式3下LED状态:0=全灭 1=全亮// 按键相关变量unsigned char key_value; // 按键扫描值unsigned char key_old, key_down;// 按键旧值/下降沿unsigned int key_dly = 0; // 按键消抖延时unsigned int led_dly = 0; // LED刷新延时// ==================== 函数声明 ====================void Timer0_Init(void);void Key_Scan(void);void LED_Proc(void);// ==================== 主函数 ====================void main(void){ // AI8051U核心配置 EAXFR = 1;// 使能扩展RAM访问 WTST = 0; // 关闭等待状态 CKCON = 0;// 时钟控制寄存器默认配置 // 端口模式配置:P1口推挽输出(LED),P3口准双向输入(按键) P1M0 = 0xFF; P1M1 = 0x00;// P1口推挽输出 P3M0 = 0x00; P3M1 = 0x00;// P3口准双向输入(默认上拉) // 定时器0初始化(1ms中断) Timer0_Init(); EA = 1;// 开启总中断 // 初始化LED为全灭 LED_PORT = 0xFF; while(1) { Key_Scan(); // 按键扫描 LED_Proc(); // LED逻辑处理 }}// ==================== 定时器0初始化(1ms中断) ====================void Timer0_Init(void){ TMOD |= 0x01;// 定时器0工作模式1(16位) // 11.0592MHz晶振,定时1ms初值 TH0 = 0xFC; TL0 = 0x66; ET0 = 1; // 开启定时器0中断 TR0 = 1; // 启动定时器0}// ==================== 定时器0中断服务函数(1ms) ====================void Timer0_Isr(void) interrupt 1{ // 重装初值 TH0 = 0xFC; TL0 = 0x66; // 计时变量累加 if(key_dly < 20) key_dly++; // 按键消抖20ms if(led_dly < 200) led_dly++; // LED刷新200ms}// ==================== 按键扫描函数(修正位操作问题) ====================void Key_Scan(void){ if(key_dly < 20) return;// 未到消抖时间 key_dly = 0; // 重置消抖延时 // 扫描P32-P35按键(低电平有效,通过位掩码判断) key_value = 0; if((P3 & KEY1_MASK) == 0) key_value = 1;// P32按键(模式切换) if((P3 & KEY2_MASK) == 0) key_value = 2;// P33按键(方向切换) if((P3 & KEY3_MASK) == 0) key_value = 3;// P34按键(LED加1) if((P3 & KEY4_MASK) == 0) key_value = 4;// P35按键(LED减1) // 下降沿检测:仅捕获按键按下的瞬间 key_down = key_value & (key_old ^ key_value); key_old = key_value; // 按键功能处理 switch(key_down) { case 1:// P32:模式切换(1→2→3→1) led_mode++; if(led_mode > 3) led_mode = 1; flow_pos = 0; single_led = 0; break; case 2:// P33:流水灯方向切换 flow_dir = !flow_dir; break; case 3:// P34:模式2下LED加1 if(led_mode == 2) { single_led++; if(single_led > 7) single_led = 0; } break; case 4:// P35:模式2下LED减1 if(led_mode == 2) { if(single_led == 0) single_led = 7; else single_led--; } break; default: break; }}// ==================== LED逻辑处理函数 ====================void LED_Proc(void){ if(led_dly < 200) return;// 未到刷新时间 led_dly = 0; // 重置LED延时 switch(led_mode) { // 模式1:流水灯 case 1: LED_PORT = 0xFF;// 先熄灭所有LED if(flow_dir == 0)// 左→右(P10→P17) { LED_PORT &= ~(1 << flow_pos); flow_pos++; if(flow_pos > 7) flow_pos = 0; } else// 右→左(P17→P10) { LED_PORT &= ~(1 << (7 - flow_pos)); flow_pos++; if(flow_pos > 7) flow_pos = 0; } break; // 模式2:单独LED控制 case 2: LED_PORT = 0xFF;// 熄灭所有LED LED_PORT &= ~(1 << single_led);// 点亮指定LED break; // 模式3:全亮/全灭切换 case 3: all_led_state = !all_led_state; LED_PORT = all_led_state ? 0x00 : 0xFF; break; default: led_mode = 1;// 异常模式切回流水灯 break; }} 顺利完成AI8051U AIcube实验一,效果非常好,AI很好用!
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2026-01-14) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
//USBLIB_OUT_Done(); //查询方式处理USB接收的数据
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
printf_usb("Hello World !\r\n");
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
//<<AICUBE_USER_PREINITIAL_CODE_BEGIN>>
// 在此添加用户预初始化代码
//<<AICUBE_USER_PREINITIAL_CODE_END>>
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
PORT4_Init(); //P4口初始化
delay_ms(1);
USBLIB_Init(); //USB库初始化
delay_ms(1);
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(34); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// P4口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT4_Init(void)
{
SetP4nInitLevelHigh(PIN_ALL); //设置P4初始化电平
SetP4nQuasiMode(PIN_7 | PIN_5 | PIN_4 | PIN_3 | PIN_2 | PIN_1 | PIN_0); //设置P4.7,P4.5,P4.4,P4.3,P4.2,P4.1,P4.0为准双向口模式
SetP4nPushPullMode(PIN_6); //设置P4.6为推挽输出模式
DisableP4nPullUp(PIN_ALL); //关闭P4内部上拉电阻
DisableP4nPullDown(PIN_ALL); //关闭P4内部下拉电阻
DisableP4nSchmitt(PIN_ALL); //使能P4施密特触发
SetP4nSlewRateNormal(PIN_ALL); //设置P4一般翻转速度
SetP4nDrivingNormal(PIN_ALL); //设置P4一般驱动能力
SetP4nDigitalInput(PIN_ALL); //使能P4数字信号输入功能
//<<AICUBE_USER_PORT4_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_PORT4_INITIAL_END>>
}
////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
usb_init(); //初始化USB模块
USB_SetIntPriority(0); //设置中断为最低优先级
set_usb_ispcmd("@STCISP#"); //设置USB不停电下载命令
//<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_USBLIB_INITIAL_END>>
}
////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
WDT_Clear(); //清看门狗定时器 (防止硬件自动使能看门狗)
}
////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
if (bUsbOutReady) //查询是否有接收到USB主机发送数据
{
//<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
// 在此处添加用户处理接收数据的代码
//<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
usb_OUT_done(); //当前包的数据处理完成,通知USB主机可以发送下一包数据
}
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
顺利完成AI8051U AIcube实验二,官方讲解视频非常详细,适合零基础小白学习!
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2026-01-14) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
USBLIB_OUT_Done(); //查询方式处理USB接收的数据
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
//<<AICUBE_USER_PREINITIAL_CODE_BEGIN>>
// 在此添加用户预初始化代码
//<<AICUBE_USER_PREINITIAL_CODE_END>>
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
PORT4_Init(); //P4口初始化
delay_ms(1);
USBLIB_Init(); //USB库初始化
delay_ms(1);
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(34); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// P4口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT4_Init(void)
{
SetP4nInitLevelHigh(PIN_ALL); //设置P4初始化电平
SetP4nQuasiMode(PIN_7 | PIN_6 | PIN_4 | PIN_3 | PIN_2 | PIN_1 | PIN_0); //设置P4.7,P4.6,P4.4,P4.3,P4.2,P4.1,P4.0为准双向口模式
SetP4nPushPullMode(PIN_5); //设置P4.5为推挽输出模式
DisableP4nPullUp(PIN_ALL); //关闭P4内部上拉电阻
DisableP4nPullDown(PIN_ALL); //关闭P4内部下拉电阻
DisableP4nSchmitt(PIN_ALL); //使能P4施密特触发
SetP4nSlewRateNormal(PIN_ALL); //设置P4一般翻转速度
SetP4nDrivingNormal(PIN_ALL); //设置P4一般驱动能力
SetP4nDigitalInput(PIN_ALL); //使能P4数字信号输入功能
//<<AICUBE_USER_PORT4_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_PORT4_INITIAL_END>>
}
////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
usb_init(); //初始化USB模块
USB_SetIntPriority(0); //设置中断为最低优先级
set_usb_ispcmd("@STCISP#"); //设置USB不停电下载命令
//<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_USBLIB_INITIAL_END>>
}
////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
WDT_Clear(); //清看门狗定时器 (防止硬件自动使能看门狗)
}
////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
if (bUsbOutReady) //查询是否有接收到USB主机发送数据
{
//<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
// USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
// 在此处添加用户处理接收数据的代码
if (UsbOutBuffer == 6)
printf_usb("Hello World !\r\n");
else if (UsbOutBuffer == 7)
printf_usb("China !\r\n");
//<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
usb_OUT_done(); //当前包的数据处理完成,通知USB主机可以发送下一包数据
}
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
页:
[1]
2