神农鼎
发表于 2025-3-23 16:21:48
RTC实时时钟部分讲解-闹钟定时
#include <AI8051U.H>
#include "ai_usb.h"
bit alarm_flag = 0;
void rtc_isr(void) interrupt 36
{
alarm_flag = 1;
RTCIF = 0;//清空所有中断
}
void main(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 口为准双向口模式
usb_init();
EA = 1;
P40 = 0;
X32KCR = 0xc0;//启动外部 32K 晶振
while (!(X32KCR & 0x01));//等待时钟稳定
RTCCFG &= ~0x02;//选择外部 32K 作为 RTC 时钟源
RTCIF = 0;//清除RTC中断标志
RTCIEN |= 0x80;//使能RTC闹钟中断
ALASEC = 10;//闹钟秒设定,这里设定10S
//因为没有设置初始值,所以初始值默认都是从00开始走的
//这里设置10就相当于从RTC初始化完成后开始10S就会接收到闹钟中断
RTCCR = 0x01;// RTC 使能
RTCCFG |= 0x01;//触发 RTC 寄存器初始化
while(RTCCFG & 0x01);//等待RTC初始化完成
printf_usb("RTC Start\r\n");
while(1)
{
if(alarm_flag)//闹钟中断到了
{
alarm_flag = 0;
printf_usb("alarm!\r\n");//打印一下闹钟到达的信息
}
if(bUsbOutReady)//读取是否发送消息
{
printf_usb("this_sec:%d\r\n",(int)SEC);//发送消息的时候返回当前的秒数
usb_OUT_done();//每次处理完OUT信息,最后都要调用这个函数
}
}
}
神农鼎
发表于 2025-3-23 16:25:45
/*
如何获得上面这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不停电下载,具体见相应部分的说明。
*/
HHF
发表于 2025-3-24 08:25:45
定时200us,假如主程序运行时间周期需要较长时间,这个定时对程序运行的影响有哪些。
王昱顺
发表于 2025-3-24 08:37:15
HHF 发表于 2025-3-24 08:25
定时200us,假如主程序运行时间周期需要较长时间,这个定时对程序运行的影响有哪些。 ...
如果是通过中断方式,中断函数会打断正在执行的主程序,执行完中断函数后面那个再继续执行主程序
如果中断函数内执行了堵塞的程序,就会对主程序的执行速度造成很大的影响
所以建议中断函数内不要执行太过于复杂的任务
xxw123
发表于 2025-3-30 09:54:48
楼主这一期视频非常好,非常适合我这样的小白,希望后面再接上其他功能的讲解,比如测温,PWM等,期待
神农鼎
发表于 2025-3-30 10:26:57
有冲哥的视频,可以先学习
神农鼎
发表于 2025-3-31 09:59:02
//学习 AiCube,
//必须使用最新的 AIapp-ISP V6.96I 以上版本软件
//必须重新添加头文件
//要运行扩展中断号软件一次
深圳国芯人工智能有限公司-工具软件
////////////////////////////////////////
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-03-31) 创建文件
////////////////////////////////////////
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
bit t0_flag = 0;
//定义1个位变量,T0 事件位变量标志,记录定时器0已产生中断
//供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务不堵塞其他中断
bit t1_flag = 0;
//定义1个位变量,T1 事件位变量标志,记录定时器1已产生中断!
//供主循环査询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
bit INT0_Flag = 0;
//定义1个位变量,INT0 事件位变量标志,记录INT0已产生中断
//供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务不堵塞其他中断
bit INT1_Flag = 0;
//定义1个位变量,INT1 事件位变量标志,记录INT1已产生中断
//供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务不堵塞其他中断
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
SYS_Init();
P40 = 0; //供电给P00 - P07 指示灯
while (1)
{
if(t0_flag)//主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0;//清 0,T0事件位变量标志t0_flag
P07 = ~P07;
//P07指示灯取反,代表主循环在处理 T0 不急的任务
}
if(t1_flag)//主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t1_flag = 0;//清 0,T1事件位变量标志t1_flag
P06 = ~P06;
//P06指示灯取反,代表主循环在处理 T1 不急的任务
}
if(INT0_Flag)//主循环中查询,INT0是否已产生中断,是否有需要处理的INT0事件
{
INT0_Flag = 0;//清 0,INT0事件位变量标志 INT0_Flag
P05 = ~P05;
//P05指示灯取反,代表主循环在处理 INT0 不急的任务
}
if(INT1_Flag)//主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
INT1_Flag = 0;//清 0,INT1事件位变量标志 INT1_Flag
P04 = ~P04;
//P04指示灯取反,代表主循环在处理 INT1 不急的任务
}
// USBLIB_OUT_Done(); //查询方式处理USB接收的数据
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
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口为准双向口模式
CLK_Init(); //时钟模块初始化
PORT0_Init(); //P0初始化
PORT1_Init(); //P1初始化
PORT2_Init(); //P2初始化
PORT3_Init(); //P3初始化
PORT4_Init(); //P4初始化
PORT5_Init(); //P5初始化
TIMER0_Init(); //定时器0初始化
TIMER1_Init(); //定时器1初始化
TIMER2_Init(); //定时器2初始化
TIMER3_Init(); //定时器3初始化
TIMER4_Init(); //定时器4初始化
EXTI0_Init(); //INT0初始化
EXTI1_Init(); //INT1初始化
EXTI2_Init(); //INT2初始化
EXTI3_Init(); //INT3初始化
USBLIB_Init(); //USB库初始化
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// 定时器0中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER0_ISR(void) interrupt TMR0_VECTOR
{
P00=~P00;
//P00 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag=1;
//t0_flag置1,是通知主循环处理部分 T0 中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
////////////////////////////////////////
// 定时器1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER1_ISR(void) interrupt TMR1_VECTOR
{
P01=~P01;
//P01 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag=1;
//t1_flag置1,是通知主循环处理部分 T1 中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
////////////////////////////////////////
// 定时器2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_ISR(void) interrupt TMR2_VECTOR
{
}
////////////////////////////////////////
// 定时器3中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER3_ISR(void) interrupt TMR3_VECTOR
{
}
////////////////////////////////////////
// 定时器4中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER4_ISR(void) interrupt TMR4_VECTOR
{
}
////////////////////////////////////////
// 外部中断INT0中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI0_ISR(void) interrupt INT0_VECTOR
{
P02=~P02;
//P02 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
INT0_Flag=1;
//INT0_Flag置1,是通知主循环处理部分 INT0 中断事件不需要特急处理的任务
//置1,记录INT0 已产生中断,供主循环查询判断有无需处理的INT0任务
}
////////////////////////////////////////
// 外部中断INT1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI1_ISR(void) interrupt INT1_VECTOR
{
P03=~P03;
//P02 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
INT1_Flag=1;
//INT1_Flag置1,是通知主循环处理部分 INT1 中断事件不需要特急处理的任务
//置1,记录INT1 已产生中断,供主循环查询判断有无需处理的INT1任务
}
////////////////////////////////////////
// 外部中断INT2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI2_ISR(void) interrupt INT2_VECTOR
{
}
////////////////////////////////////////
// 外部中断INT3中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI3_ISR(void) interrupt INT3_VECTOR
{
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_40M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_MCLK2_BYPASS(); //旁路MCLK2,直接使用MCLK选择
CLK_SYSCLK_Divider(1); //设置系统时钟分频系数
CLK_HSIOCK_MCLK(); //选择MCLK主时钟作为高速外设时钟源
CLK_HSIOCK_Divider(1); //设置高速外设时钟预分频系数
CLK_SPICLK_Divider(1); //设置SPI时钟预分频系数
CLK_I2SCLK_Divider(1); //设置I2S时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
}
////////////////////////////////////////
// P0口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT0_Init(void)
{
SetP0nQuasiMode(BIT_ALL); //设置P0为准双向口模式
DisableP0nPullUp(BIT_ALL); //关闭P0内部上拉电阻
DisableP0nPullDown(BIT_ALL); //关闭P0内部下拉电阻
DisableP0nSchmitt(BIT_ALL); //使能P0施密特触发
SetP0nSlewRateNormal(BIT_ALL); //设置P0一般翻转速度
SetP0nDrivingNormal(BIT_ALL); //设置P0一般驱动能力
SetP0nDigitalInput(BIT_ALL); //使能P0数字信号输入功能
}
////////////////////////////////////////
// P1口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT1_Init(void)
{
SetP1nQuasiMode(BIT_ALL); //设置P1为准双向口模式
DisableP1nPullUp(BIT_ALL); //关闭P1内部上拉电阻
DisableP1nPullDown(BIT_ALL); //关闭P1内部下拉电阻
DisableP1nSchmitt(BIT_ALL); //使能P1施密特触发
SetP1nSlewRateNormal(BIT_ALL); //设置P1一般翻转速度
SetP1nDrivingNormal(BIT_ALL); //设置P1一般驱动能力
SetP1nDigitalInput(BIT_ALL); //使能P1数字信号输入功能
}
////////////////////////////////////////
// P2口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT2_Init(void)
{
SetP2nQuasiMode(BIT_ALL); //设置P2为准双向口模式
DisableP2nPullUp(BIT_ALL); //关闭P2内部上拉电阻
DisableP2nPullDown(BIT_ALL); //关闭P2内部下拉电阻
DisableP2nSchmitt(BIT_ALL); //使能P2施密特触发
SetP2nSlewRateNormal(BIT_ALL); //设置P2一般翻转速度
SetP2nDrivingNormal(BIT_ALL); //设置P2一般驱动能力
SetP2nDigitalInput(BIT_ALL); //使能P2数字信号输入功能
}
////////////////////////////////////////
// P3口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT3_Init(void)
{
SetP3nQuasiMode(BIT_ALL); //设置P3为准双向口模式
DisableP3nPullUp(BIT_ALL); //关闭P3内部上拉电阻
DisableP3nPullDown(BIT_ALL); //关闭P3内部下拉电阻
DisableP3nSchmitt(BIT_ALL); //使能P3施密特触发
SetP3nSlewRateNormal(BIT_ALL); //设置P3一般翻转速度
SetP3nDrivingNormal(BIT_ALL); //设置P3一般驱动能力
SetP3nDigitalInput(BIT_ALL); //使能P3数字信号输入功能
}
////////////////////////////////////////
// P4口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT4_Init(void)
{
SetP4nQuasiMode(BIT_ALL); //设置P4为准双向口模式
DisableP4nPullUp(BIT_ALL); //关闭P4内部上拉电阻
DisableP4nPullDown(BIT_ALL); //关闭P4内部下拉电阻
DisableP4nSchmitt(BIT_ALL); //使能P4施密特触发
SetP4nSlewRateNormal(BIT_ALL); //设置P4一般翻转速度
SetP4nDrivingNormal(BIT_ALL); //设置P4一般驱动能力
SetP4nDigitalInput(BIT_ALL); //使能P4数字信号输入功能
}
////////////////////////////////////////
// P5口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT5_Init(void)
{
SetP5nQuasiMode(BIT_ALL); //设置P5为准双向口模式
DisableP5nPullUp(BIT_ALL); //关闭P5内部上拉电阻
DisableP5nPullDown(BIT_ALL); //关闭P5内部下拉电阻
DisableP5nSchmitt(BIT_ALL); //使能P5施密特触发
SetP5nSlewRateNormal(BIT_ALL); //设置P5一般翻转速度
SetP5nDrivingNormal(BIT_ALL); //设置P5一般驱动能力
SetP5nDigitalInput(BIT_ALL); //使能P5数字信号输入功能
}
////////////////////////////////////////
// 定时器0初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER0_Init(void)
{
#define T0_PSCR 51
#define T0_RELOAD (65536 - SYSCLK / 12 / (T0_PSCR + 1) * 1 / 1)
TIMER0_TimerMode(); //设置定时器0为定时模式
TIMER0_12TMode(); //设置定时器0为12T模式
TIMER0_Mode0(); //设置定时器0为模式0 (16位自动重载模式)
TIMER0_DisableGateINT0(); //禁止定时器0门控
TIMER0_SetIntPriority(0); //设置中断为最低优先级
TIMER0_EnableInt(); //使能定时器0中断
TIMER0_SetPrescale(T0_PSCR); //设置定时器0的8位预分频
TIMER0_SetReload16(T0_RELOAD); //设置定时器0的16位重载值
TIMER0_Run(); //定时器0开始运行
}
////////////////////////////////////////
// 定时器1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER1_Init(void)
{
#define T1_PSCR 25
#define T1_RELOAD (65536 - SYSCLK / 12 / (T1_PSCR + 1) * 500 / 1000)
TIMER1_TimerMode(); //设置定时器1为定时模式
TIMER1_12TMode(); //设置定时器1为12T模式
TIMER1_Mode0(); //设置定时器1为模式0 (16位自动重载模式)
TIMER1_DisableGateINT1(); //禁止定时器1门控
TIMER1_SetIntPriority(0); //设置中断为最低优先级
TIMER1_EnableInt(); //使能定时器1中断
TIMER1_SetPrescale(T1_PSCR); //设置定时器1的8位预分频
TIMER1_SetReload16(T1_RELOAD); //设置定时器1的16位重载值
TIMER1_Run(); //定时器1开始运行
}
////////////////////////////////////////
// 定时器2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_Init(void)
{
#define T2_PSCR 1
#define T2_RELOAD (65536 - SYSCLK / 12 / (T2_PSCR + 1) * 10 / 1000)
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_12TMode(); //设置定时器2为12T模式
TIMER2_EnableInt(); //使能定时器2中断
TIMER2_SetPrescale(T2_PSCR); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
}
////////////////////////////////////////
// 定时器3初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER3_Init(void)
{
#define T3_PSCR 0
#define T3_RELOAD (65536 - SYSCLK / (T3_PSCR + 1) * 200 / 1000000)
TIMER3_TimerMode(); //设置定时器3为定时模式
TIMER3_1TMode(); //设置定时器3为1T模式
TIMER3_EnableInt(); //使能定时器3中断
TIMER3_SetPrescale(T3_PSCR); //设置定时器3的8位预分频
TIMER3_SetReload16(T3_RELOAD); //设置定时器3的16位重载值
TIMER3_Run(); //定时器3开始运行
}
////////////////////////////////////////
// 定时器4初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER4_Init(void)
{
#define T4_PSCR 0
#define T4_RELOAD (65536 - SYSCLK / (T4_PSCR + 1) * 5 / 1000000)
TIMER4_TimerMode(); //设置定时器4为定时模式
TIMER4_1TMode(); //设置定时器4为1T模式
TIMER4_EnableInt(); //使能定时器4中断
TIMER4_SetPrescale(T4_PSCR); //设置定时器4的8位预分频
TIMER4_SetReload16(T4_RELOAD); //设置定时器4的16位重载值
TIMER4_Run(); //定时器4开始运行
}
////////////////////////////////////////
// 外部中断INT0初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI0_Init(void)
{
INT0_FallingInt(); //设置外部中断为下降沿中断
INT0_SetIntPriority(0); //设置中断为最低优先级
INT0_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// 外部中断INT1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI1_Init(void)
{
INT1_FallingInt(); //设置外部中断为下降沿中断
INT1_SetIntPriority(1); //设置中断为较低优先级
INT1_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// 外部中断INT2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI2_Init(void)
{
INT2_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// 外部中断INT3初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI3_Init(void)
{
INT3_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
usb_init(); //初始化USB模块
USB_SetIntPriority(0); //设置中断为最低优先级
set_usb_ispcmd("@STCISP#"); //设置USB不停电下载命令
}
////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
}
////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
if (bUsbOutReady) //查询是否有接收到数据
{
USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
usb_OUT_done(); //当前包的数据处理完成
}
}
神农鼎
发表于 2025-3-31 10:25:45
一起学 AiCube 工具 @ AIapp-ISP V6.95J 及以上版本
===已更新到 J 版本,根据本内部培训视频讲解发现的问题
后续会重新正式录制新的讲解视频
大家一起用 AiCube 来开发 Ai8051U-32Bit
https://v.stcai.com/sv/1011abee-195eab8e444/1011abee-195eab8e444.mp4
https://www.stcaimcu.com/data/download/Tools/AIapp-ISP-v6.95J.zip
国学芯用
发表于 2025-3-31 11:15:38
//学习 AiCube
//必须使用最新的 AIapp-ISP V6.95I 以上版本软件
//必须重新添加头文件
//要运行扩展中断号软件一次
深圳国芯人工智能有限公司-工具软件
附件已上传正确的代码!!!
视频里的可以位寻址的位取反代码可以如下用法:
==【位用 ! 取反,字节用~取反】
==但可以位寻址的位取反,可以用【 ! 取反,~ 取反】
==尽量【位用 ! 取反】
附件代码:
T0 / T1 / T2 / T3 / T4, INT0 / INT1 实验
使用 AiCube 外设智能化配置工具生成项目文件,再修改后的原代码:
===要安装最新的 AIapp-ISP V6.95I 或以上版本
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
bit t0_flag = 0;
//定义1个位变量,T0 事件位变量标志,记录定时器0已产生中断
//供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务不堵塞其他中断
bit t1_flag = 0;
//定义1个位变量,T1 事件位变量标志,记录定时器1已产生中断!
//供主循环査询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
bit INT0_Flag = 0;
//定义1个位变量,INT0 事件位变量标志,记录INT0已产生中断
//供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务不堵塞其他中断
bit INT1_Flag = 0;
//定义1个位变量,INT1 事件位变量标志,记录INT1已产生中断
//供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务不堵塞其他中断
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
SYS_Init();
P40 = 0; //供电给P00 - P07 指示灯
while (1)
{
if(t0_flag)//主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0;//清 0,T0事件位变量标志t0_flag
P07 = !P07;
//P07指示灯取反,代表主循环在处理 T0 不急的任务
}
if(t1_flag)//主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t1_flag = 0;//清 0,T1事件位变量标志t1_flag
P06 = !P06;
//P06指示灯取反,代表主循环在处理 T1 不急的任务
}
if(INT0_Flag)//主循环中查询,INT0是否已产生中断,是否有需要处理的INT0事件
{
INT0_Flag = 0;//清 0,INT0事件位变量标志 INT0_Flag
P05 = !P05;
//P05指示灯取反,代表主循环在处理 INT0 不急的任务
}
if(INT1_Flag)//主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
INT1_Flag = 0;//清 0,INT1事件位变量标志 INT1_Flag
P04 = !P04;
//P04指示灯取反,代表主循环在处理 INT1 不急的任务
}
// USBLIB_OUT_Done(); //查询方式处理USB接收的数据
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
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口为准双向口模式
CLK_Init(); //时钟模块初始化
PORT0_Init(); //P0初始化
PORT1_Init(); //P1初始化
PORT2_Init(); //P2初始化
PORT3_Init(); //P3初始化
PORT4_Init(); //P4初始化
PORT5_Init(); //P5初始化
TIMER0_Init(); //定时器0初始化
TIMER1_Init(); //定时器1初始化
TIMER2_Init(); //定时器2初始化
TIMER3_Init(); //定时器3初始化
TIMER4_Init(); //定时器4初始化
EXTI0_Init(); //INT0初始化
EXTI1_Init(); //INT1初始化
EXTI2_Init(); //INT2初始化
EXTI3_Init(); //INT3初始化
USBLIB_Init(); //USB库初始化
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// 定时器0中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER0_ISR(void) interrupt TMR0_VECTOR
{
P00=!P00;
//P00 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag=1;
//t0_flag置1,是通知主循环处理部分 T0 中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
////////////////////////////////////////
// 定时器1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER1_ISR(void) interrupt TMR1_VECTOR
{
P01=!P01;
//P01 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag=1;
//t1_flag置1,是通知主循环处理部分 T1 中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
////////////////////////////////////////
// 定时器2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_ISR(void) interrupt TMR2_VECTOR
{
}
////////////////////////////////////////
// 定时器3中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER3_ISR(void) interrupt TMR3_VECTOR
{
}
////////////////////////////////////////
// 定时器4中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER4_ISR(void) interrupt TMR4_VECTOR
{
}
////////////////////////////////////////
// 外部中断INT0中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI0_ISR(void) interrupt INT0_VECTOR
{
P02=!P02;
//P02 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
INT0_Flag=1;
//INT0_Flag置1,是通知主循环处理部分 INT0 中断事件不需要特急处理的任务
//置1,记录INT0 已产生中断,供主循环查询判断有无需处理的INT0任务
}
////////////////////////////////////////
// 外部中断INT1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI1_ISR(void) interrupt INT1_VECTOR
{
P03=!P03;
//P02 灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
INT1_Flag=1;
//INT1_Flag置1,是通知主循环处理部分 INT1 中断事件不需要特急处理的任务
//置1,记录INT1 已产生中断,供主循环查询判断有无需处理的INT1任务
}
////////////////////////////////////////
// 外部中断INT2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI2_ISR(void) interrupt INT2_VECTOR
{
}
////////////////////////////////////////
// 外部中断INT3中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI3_ISR(void) interrupt INT3_VECTOR
{
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_40M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_MCLK2_BYPASS(); //旁路MCLK2,直接使用MCLK选择
CLK_SYSCLK_Divider(1); //设置系统时钟分频系数
CLK_HSIOCK_MCLK(); //选择MCLK主时钟作为高速外设时钟源
CLK_HSIOCK_Divider(1); //设置高速外设时钟预分频系数
CLK_SPICLK_Divider(1); //设置SPI时钟预分频系数
CLK_I2SCLK_Divider(1); //设置I2S时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
}
////////////////////////////////////////
// P0口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT0_Init(void)
{
SetP0nQuasiMode(BIT_ALL); //设置P0为准双向口模式
DisableP0nPullUp(BIT_ALL); //关闭P0内部上拉电阻
DisableP0nPullDown(BIT_ALL); //关闭P0内部下拉电阻
DisableP0nSchmitt(BIT_ALL); //使能P0施密特触发
SetP0nSlewRateNormal(BIT_ALL); //设置P0一般翻转速度
SetP0nDrivingNormal(BIT_ALL); //设置P0一般驱动能力
SetP0nDigitalInput(BIT_ALL); //使能P0数字信号输入功能
}
////////////////////////////////////////
// P1口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT1_Init(void)
{
SetP1nQuasiMode(BIT_ALL); //设置P1为准双向口模式
DisableP1nPullUp(BIT_ALL); //关闭P1内部上拉电阻
DisableP1nPullDown(BIT_ALL); //关闭P1内部下拉电阻
DisableP1nSchmitt(BIT_ALL); //使能P1施密特触发
SetP1nSlewRateNormal(BIT_ALL); //设置P1一般翻转速度
SetP1nDrivingNormal(BIT_ALL); //设置P1一般驱动能力
SetP1nDigitalInput(BIT_ALL); //使能P1数字信号输入功能
}
////////////////////////////////////////
// P2口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT2_Init(void)
{
SetP2nQuasiMode(BIT_ALL); //设置P2为准双向口模式
DisableP2nPullUp(BIT_ALL); //关闭P2内部上拉电阻
DisableP2nPullDown(BIT_ALL); //关闭P2内部下拉电阻
DisableP2nSchmitt(BIT_ALL); //使能P2施密特触发
SetP2nSlewRateNormal(BIT_ALL); //设置P2一般翻转速度
SetP2nDrivingNormal(BIT_ALL); //设置P2一般驱动能力
SetP2nDigitalInput(BIT_ALL); //使能P2数字信号输入功能
}
////////////////////////////////////////
// P3口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT3_Init(void)
{
SetP3nQuasiMode(BIT_ALL); //设置P3为准双向口模式
DisableP3nPullUp(BIT_ALL); //关闭P3内部上拉电阻
DisableP3nPullDown(BIT_ALL); //关闭P3内部下拉电阻
DisableP3nSchmitt(BIT_ALL); //使能P3施密特触发
SetP3nSlewRateNormal(BIT_ALL); //设置P3一般翻转速度
SetP3nDrivingNormal(BIT_ALL); //设置P3一般驱动能力
SetP3nDigitalInput(BIT_ALL); //使能P3数字信号输入功能
}
////////////////////////////////////////
// P4口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT4_Init(void)
{
SetP4nQuasiMode(BIT_ALL); //设置P4为准双向口模式
DisableP4nPullUp(BIT_ALL); //关闭P4内部上拉电阻
DisableP4nPullDown(BIT_ALL); //关闭P4内部下拉电阻
DisableP4nSchmitt(BIT_ALL); //使能P4施密特触发
SetP4nSlewRateNormal(BIT_ALL); //设置P4一般翻转速度
SetP4nDrivingNormal(BIT_ALL); //设置P4一般驱动能力
SetP4nDigitalInput(BIT_ALL); //使能P4数字信号输入功能
}
////////////////////////////////////////
// P5口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT5_Init(void)
{
SetP5nQuasiMode(BIT_ALL); //设置P5为准双向口模式
DisableP5nPullUp(BIT_ALL); //关闭P5内部上拉电阻
DisableP5nPullDown(BIT_ALL); //关闭P5内部下拉电阻
DisableP5nSchmitt(BIT_ALL); //使能P5施密特触发
SetP5nSlewRateNormal(BIT_ALL); //设置P5一般翻转速度
SetP5nDrivingNormal(BIT_ALL); //设置P5一般驱动能力
SetP5nDigitalInput(BIT_ALL); //使能P5数字信号输入功能
}
////////////////////////////////////////
// 定时器0初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER0_Init(void)
{
#define T0_PSCR 51
#define T0_RELOAD (65536 - SYSCLK / 12 / (T0_PSCR + 1) * 1 / 1)
TIMER0_TimerMode(); //设置定时器0为定时模式
TIMER0_12TMode(); //设置定时器0为12T模式
TIMER0_Mode0(); //设置定时器0为模式0 (16位自动重载模式)
TIMER0_DisableGateINT0(); //禁止定时器0门控
TIMER0_SetIntPriority(0); //设置中断为最低优先级
TIMER0_EnableInt(); //使能定时器0中断
TIMER0_SetPrescale(T0_PSCR); //设置定时器0的8位预分频
TIMER0_SetReload16(T0_RELOAD); //设置定时器0的16位重载值
TIMER0_Run(); //定时器0开始运行
}
////////////////////////////////////////
// 定时器1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER1_Init(void)
{
#define T1_PSCR 25
#define T1_RELOAD (65536 - SYSCLK / 12 / (T1_PSCR + 1) * 500 / 1000)
TIMER1_TimerMode(); //设置定时器1为定时模式
TIMER1_12TMode(); //设置定时器1为12T模式
TIMER1_Mode0(); //设置定时器1为模式0 (16位自动重载模式)
TIMER1_DisableGateINT1(); //禁止定时器1门控
TIMER1_SetIntPriority(0); //设置中断为最低优先级
TIMER1_EnableInt(); //使能定时器1中断
TIMER1_SetPrescale(T1_PSCR); //设置定时器1的8位预分频
TIMER1_SetReload16(T1_RELOAD); //设置定时器1的16位重载值
TIMER1_Run(); //定时器1开始运行
}
////////////////////////////////////////
// 定时器2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_Init(void)
{
#define T2_PSCR 1
#define T2_RELOAD (65536 - SYSCLK / 12 / (T2_PSCR + 1) * 10 / 1000)
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_12TMode(); //设置定时器2为12T模式
TIMER2_EnableInt(); //使能定时器2中断
TIMER2_SetPrescale(T2_PSCR); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
}
////////////////////////////////////////
// 定时器3初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER3_Init(void)
{
#define T3_PSCR 0
#define T3_RELOAD (65536 - SYSCLK / (T3_PSCR + 1) * 200 / 1000000)
TIMER3_TimerMode(); //设置定时器3为定时模式
TIMER3_1TMode(); //设置定时器3为1T模式
TIMER3_EnableInt(); //使能定时器3中断
TIMER3_SetPrescale(T3_PSCR); //设置定时器3的8位预分频
TIMER3_SetReload16(T3_RELOAD); //设置定时器3的16位重载值
TIMER3_Run(); //定时器3开始运行
}
////////////////////////////////////////
// 定时器4初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER4_Init(void)
{
#define T4_PSCR 0
#define T4_RELOAD (65536 - SYSCLK / (T4_PSCR + 1) * 5 / 1000000)
TIMER4_TimerMode(); //设置定时器4为定时模式
TIMER4_1TMode(); //设置定时器4为1T模式
TIMER4_EnableInt(); //使能定时器4中断
TIMER4_SetPrescale(T4_PSCR); //设置定时器4的8位预分频
TIMER4_SetReload16(T4_RELOAD); //设置定时器4的16位重载值
TIMER4_Run(); //定时器4开始运行
}
////////////////////////////////////////
// 外部中断INT0初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI0_Init(void)
{
INT0_FallingInt(); //设置外部中断为下降沿中断
INT0_SetIntPriority(0); //设置中断为最低优先级
INT0_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// 外部中断INT1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI1_Init(void)
{
INT1_FallingInt(); //设置外部中断为下降沿中断
INT1_SetIntPriority(1); //设置中断为较低优先级
INT1_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// 外部中断INT2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI2_Init(void)
{
INT2_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// 外部中断INT3初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI3_Init(void)
{
INT3_EnableInt(); //使能外部中断
}
////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
usb_init(); //初始化USB模块
USB_SetIntPriority(0); //设置中断为最低优先级
set_usb_ispcmd("@STCISP#"); //设置USB不停电下载命令
}
////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
}
////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
if (bUsbOutReady) //查询是否有接收到数据
{
USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
usb_OUT_done(); //当前包的数据处理完成
}
}
神农鼎
发表于 2025-3-31 11:40:22
但 KEIL C251 实际 对于可以位寻址的位的操作,
[ !, ~ ], 是一样的,等我们研发人员反汇编后来回答