ZIJIN_CHJ 发表于 2025-7-9 20:51
数码管仿真显示,
数码管仿真显示
第7课定时器中断
/*************功能说明 **************
本例程基于AI8051U为主控芯片进行编写测试.配合USB不停电下载,
使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
程序使用P2口来演示跑马灯,输出低驱动。
下载时, 选择时钟 24MHZ (用户可自行修改频率).
******************************************/
/*------------------ 头文件声明 ---------------------*/
#include "ai8051u.H"
#include "stc32_stc8_usb.H"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
#define MAIN_Fosc 24000000UL //系统频率
/*------------------ 用户变量声明 ---------------------*/
u8 x = 20;
u8 y = 0;
u8 start = 0;
u8 j = 1;
u8 Run_state; //运行状态
//void Timer0_Init(void) //3秒@24.000MHz,24位自动重载
//{
// TM0PS = 0x5B; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
// AUXR &= 0x7F; //定时器时钟12T模式
// TMOD &= 0xF0; //设置定时器模式
// TL0 = 0x3F; //设置定时初始值
// TH0 = 0x01; //设置定时初始值
// TF0 = 0; //清除TF0标志
// TR0 = 1; //定时器0开始计时
// ET0 = 1; //使能定时器0中断
//}
void Timer0_Init(void) //500毫秒@24.000MHz,24位自动重载
{
TM0PS = 0x0F; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xDC; //设置定时初始值
TH0 = 0x0B; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
}
void delay_ms(u8 ms); //延时函数声明
/*------------------ MAIN主函数 ---------------------*/
void main(void)
{
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M0 = 0x00; P0M1 = 0x00; //设置P0--P7口为标准IO口
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;
usb_init(); //USB接口配置
IE2 |= 0x80; //使能USB中断
// Timer0_Init(); //定时器0初始化
EA = 1; //全能总中断
P32 = 1;
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while(1)
{
if (bUsbOutReady)
{
USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("今天是%d年%d月%d日\r\n",25,12,28);
usb_OUT_done();
}
//任务1:P32按键按下,串口打印出按键按下的次数,同时LED灯亮3秒灭3秒
// if(P32==0)
// {
// delay_ms(10);
// if(P32==0)
// {
//
// printf("按键按下次数\xfd: %d 次\r\n",(int)j);
// j++;
// while(P32==0);
// }
// }
//任务2:按键按下,灯亮3秒后熄灭
// if(P32==0)
// {
// delay_ms(20);
// if(P32==0)
// {
// P20 = 0;
// Timer0_Init();
//
// while(P32==0);
// }
// }
//任务2:按键按下,灯亮LED0,LED1交替闪烁,再按一次两个灯都熄灭
if(P32==0)
{
delay_ms(20);
if(P32==0)
{
Run_state = !Run_state;
while(P32==0);
if(Run_state==1)
{
Timer0_Init();
}
else
{
P20 = 1;
P21 = 1;
TR0 = 0;
}
}
}
}
}
/*------------------ 中断服务函数 ---------------------*/
void Timer0_Isr(void) interrupt 1
{
// start = !start;
// P20 = start;
// P20 = 1;
// TR0 = 0;
start = !start;
P20 = start;
P21 = !start;
}
//========================================================================
// 函数: voiddelay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: 无.
// 备注:
//========================================================================
void delay_ms(u8 ms)
{
u16 i;
do{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
attach://126996.mp4
/*************功能说明 **************
本例程基于AI8051U为主控芯片进行编写测试.配合USB不停电下载,
使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
程序使用P2口来演示跑马灯,输出低驱动。
下载时, 选择时钟 24MHZ (用户可自行修改频率).
******************************************/
/*------------------ 头文件声明 ---------------------*/
#include "ai8051u.H"
#include "stc32_stc8_usb.H"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
#define MAIN_Fosc 24000000UL //系统频率
/*------------------ 用户变量声明 ---------------------*/
u8 LED1_State;
u8 LED2_State;
u8 LED3_State;
//u16 Count1=0;
//u16 Count2=0;
//u16 Count3=0;
u16 Count = {0,0,0};
u8 Led_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 num = 0;
u8 Key_num;
u8 i;
void Timer0_Init(void) //1毫秒@24.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
/*------------------ MAIN主函数 ---------------------*/
void main(void)
{
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M0 = 0x00; P0M1 = 0x00; //设置P0--P7口为标准IO口
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;
usb_init(); //USB接口配置
IE2 |= 0x80; //使能USB中断
Timer0_Init(); //定时器0初始化
EA = 1; //全能总中断
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while(1)
{
if (bUsbOutReady)
{
USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
printf("今天是%d年%d月%d日\r\n",25,12,28);
usb_OUT_done();
}
//任务1:用一个定时器实现LED1 0.3秒取反一次,LED2 0.6秒取反一次,LED3 0.9秒取反一次
// if(Count1>=300)
// {
// Count1 = 0;
// LED1_State = !LED1_State;
// P20 = LED1_State;
// }
// else if(Count2>=600)
// {
// Count2 = 0;
// LED2_State = !LED2_State;
// P21 = LED2_State;
// }
// else if(Count3>=900)
// {
// Count3 = 0;
// LED3_State = !LED3_State;
// P22 = LED3_State;
// }
// if(Count>=300)
// {
// Count = 0;
// LED1_State = !LED1_State;
// P20 = LED1_State;
// }
// if(Count>=600)
// {
// Count = 0;
// LED2_State = !LED2_State;
// P21 = LED2_State;
// }
// if(Count>=900)
// {
// Count = 0;
// LED3_State = !LED3_State;
// P22 = LED3_State;
// }
//任务2:利用数组点亮LED灯,实现流水灯效果
P2 = ~Led_State;
if(Count >= 600)
{
Count = 0;
num++;
if(num>=8)
num=0;
}
// if(Count >= 10)
// {
// Count = 0;
// if(P32==0)
// {
// Key_num++;
// if(Key_num==5)
// {
//
// num++;
// if(num>=8)
// num=0;
// }
//
// }
// else
// {
// Key_num=0;
// }
// }
}
}
/*------------------ 中断服务函数 ---------------------*/
void Timer0_Isr(void) interrupt 1
{
for(i=0;i<3;i++)
{
Count++;
}
// Count1 ++;
// Count2 ++;
// Count3 ++;
// if(Count1>=300)
// {
// Count1 = 0;
// LED1_State = !LED1_State;
// P20 = LED1_State;
//
// }
// Count2++;
// if(Count2>=600)
// {
// Count2 = 0;
// LED2_State = !LED2_State;
// P22 = LED2_State;
// }
// Count3++;
// if(Count3>=900)
// {
// Count3 = 0;
// LED3_State = !LED3_State;
// P24 = LED3_State;
//
// }
}
多任务处理函数
#include "task.h"
#include "io.h"
static TASK_COMPONENTS Task_Comps[]=
{
//状态计数 周期 函数
{0, 300, 300, Led1_Blink}, /* task 1 Period: 300ms */
{0, 600, 600, Led2_Blink}, /* task 1 Period: 600ms */
{0, 900, 900, Led3_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_Marks_Handler_Callback(void)
{
u8 i;
for(i=0;i<Tasks_Max;i++)
{
if(Task_Comps.TIMCount)
{
Task_Comps.TIMCount--;
if(Task_Comps.TIMCount==0)
{
Task_Comps.TIMCount=Task_Comps.TRITime;
Task_Comps.Run = 1;
}
}
}
}
//任务处理回调函数
void Task_Pro_Handler_Callback(void)
{
u8 i;
for(i=0;i<Tasks_Max;i++)
{
if(Task_Comps.Run)
{
Task_Comps.Run = 0;
Task_Comps.TaskHook();
}
}
}
外部中断1试验函数
#include "ai8051u.h"
#include "intrins.h"
/*--------------------------
函数名称:延时函数
函数说明:主控MCU ai8051u 32bit,24M频率
延时1秒.如果要使用_nop_(),库函数必须添加:"intrins.h"头文件
参数: 无
返回值: 无
----------------------------*/
void Delay1000ms(void) //@24.000MHz //延时函数
{
unsigned long edata i;
_nop_();
_nop_();
i = 5999998UL;
while (i) i--;
}
/*--------------------------
函数名称:主函数.
函数说明:每一个程序都有一个主函数,并且只能有一个主函数.主函数可以调用其它子函数,其它子函数
不能调用主函数
参数: 无
返回值: 无
----------------------------*/
void main(void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器 XFR
WTST = 0; //设置取程序代码等待时间
//赋值为0表示不等待.程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度
//赋值为0表示用最快速度访问.不增加额外的等待时间
P0M0 = 0x00;P0M1 = 0x00; //配置IO口为准双向口.
P1M0 = 0x00;P1M1 = 0x00;
P2M0 = 0x00;P2M1 = 0x00;
P3M0 = 0x00;P3M1 = 0x00;
P4M0 = 0x00;P4M1 = 0x00;
P5M0 = 0x00;P5M1 = 0x00;
IT1 = 1; //使能INT1上升沿和下降沿中断
EX1 = 1; //使能INT1中断
EA = 1; //开启总中断
while(1)
{
P21 = !P21;
Delay1000ms();
// if(P33 == 0)
// P20 = !P20;
}
}
/*--------------------------
函数名称:中断函数
函数说明:中断函数可以打断主函数的运行,中断函数执行完才能运行主函数
参数: 无
返回值: 无
----------------------------*/
void Int1_Isr() interrupt 2
{
P20 = !P20;
}