找回密码
 立即注册
查看: 702|回复: 10

AI8051U学习打卡(一)

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 10:00:40 | 显示全部楼层 |阅读模式

AI8051U学习打卡(一)

1. AI8051U硬件资源

Ai8051U-LQFP48 比普通 M0/M3,比 32F103C8T6 强太多的地方:

  1. **Ai8051U有TFPU@120MHz, 算力比他强, uS级硬件三角函数/浮点运算器; **
  2. Ai8051U的抗干扰比他强;
  3. Ai8051U的内部复位是专业级的复位电路,彻底省外部复位;
  4. **Ai8051U的内部时钟完全满足串口通信要求,4组串口; **
  5. **Ai8051U-LQFP48有 QSPI, i8080/M6800-TFT 接口,32F103C8T6没有; **
  6. Ai8051U的PWM支持硬件移相@120MHz ;
  7. Ai8051U是 34K SRAM ;
  8. Ai8051U是 自带硬件USB, 1个芯片就能直接USB连接电脑仿真/下载,
  9. 全球唯一 ===这个开发生态,全球最强 Ai8051U-LQFP48, RMB2.3含税

2. 开发环境搭建

官网下载地址:深圳国芯人工智能有限公司-产品_AI8051U系列

必备资料清单:

2.1. keil-C251软件设置

1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
  • +1

    楼主威武~

回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 10:03:13 | 显示全部楼层

AI8051U学习打卡(二)

2.1点灯实验

#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口定义    **************/

/*************  本地变量声明    **************/


/*************  本地函数声明    **************/

void  delay_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
    }
}

//========================================================================
// 函数: void  delay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 
//========================================================================
void  delay_ms(u8 ms)
{
     u16 i;
     do{
          i = MAIN_Fosc / 6000;
          while(--i);
     }while(--ms);
}

2.2. STC-link下载

打开一个点灯程序,按如下配置成功烧录,成功点亮led。

下面那个复位引脚作io也不要勾选,不然复位按键失效。

实物演示:

e94c643a0dc57bd1f0f6de2820d8de22.gif

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 10:05:22 | 显示全部楼层

AI8051U学习打卡(三)

3. USB不停电下载(usb-cdc-uart)

没下载不停电下载程序之前,还是之前的流水灯代码,这个时候直接只用一根usb线连接电脑是没有任何反应的。

图方便就用那个STC-link来下载。插上STC-link之后就显示出来串口了,如图所示。

然后和上一节一样正常直接烧录下面的代码就行。

#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();
        }
    }
}

不用STC-link,再次只用一个usb线连接电脑,发现识别到一个新的串口,这个是usb虚拟串口,支持任意波特率。

之后就可以直接用这个不断电下载程序了,也不用STC-link了,但是代码框架不能改,如果重新烧录之前流水灯的代码,就会又识别不到了,又只能用STC-link或者断电下载了。

image.png

3.1. printf打印

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 10:10:25 | 显示全部楼层

AI8051U学习打卡(四)

4. GPIO输入输出

#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); //等待按键松开
            }
        }
    }
}

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 11:24:08 | 显示全部楼层

AI8051U学习打卡(五)

5. 定时器中断

5.1. 定时器资源

5.2. 软件配置定时器

下载代码之后led成功每隔3秒亮灭一次,然后串口也能打印按下次数。

#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;
}

5.3. bug解决

5.3.1. keil警告

5.3.2. 串口打印乱码

5.4. 定时器时间计算

TM0PS:分频系数(psc)

(65536-[TH0,TL0]):目标计数值(arr)

Sysclk:系统时钟(40Mhz)

eg:

TM0PS = 152

[TH0,TL0] = 177

(152+1)*(65536 - 177)*12/40000000 = 2.9999781s

5.4.1. 定时器0延时3s关灯

#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");
}

8b4b4b6f89bb99854d2d3afd28eec964.gif

5.4.2. 灯交替闪烁

#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;
}

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:52
  • 最近打卡:2025-04-08 20:05:04
已绑定手机

13

主题

79

回帖

438

积分

荣誉版主

积分
438
发表于 2024-12-16 12:29:36 | 显示全部楼层

贴主的笔记很详细,给你点个赞qiang

希望你能继续坚持下去

君子知命不惑,日日自新。
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 16:03:24 | 显示全部楼层

AI8051U学习打卡(六)

6. 定时器任务调度

6.1. 任务1:

用一个定时器实现这个任务。LED1实现0.3秒取反一次,LED2实现0.6

秒取反一次,LED3实现0.9秒取反一次。

#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[3] ={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[0] >= 300)
        {
            Timer0_cnt[0] = 0;
            led1_state ^= 1;
            P00 = led1_state;
        }
        if(Timer0_cnt[1] >= 600)
        {
            Timer0_cnt[1] = 0;
            led2_state ^= 1;
            P01 = led2_state;
        }
        if(Timer0_cnt[2] >= 900)
        {
            Timer0_cnt[2] = 0;
            led3_state ^= 1;
            P02 = led3_state;
        }
    }
}

void Timer0_Isr(void) interrupt 1
{
    for(i=0;i<3;i++)
    {
        Timer0_cnt[i]++;
    }
}

6.2. 任务2:

数组点亮LED,实现流水灯。

#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[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint16_t Timer0_cnt[3] ={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[0] >= 500)
        {
           Timer0_cnt[0] = 0;
           P0 = ~LED_State[LED_pos];
           if(++LED_pos >= 8) LED_pos = 0;
        }
    }
}

void Timer0_Isr(void) interrupt 1
{
    for(i=0;i<3;i++)
    {
        Timer0_cnt[i]++;
    }
}

6.3. 任务3:

按键按下一次,LED通过数组移动一下。搭配定时器扫描消抖,不阻塞串口发送,串口稳定1s发一次。

#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[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint16_t Timer0_cnt[3] ={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[LED_pos];
      
        if(Timer0_cnt[1] >= 1000)
        {
            Timer0_cnt[1] = 0;
            printf("HELLO_AI8051U\r\n");
        }
      
        if(Timer0_cnt[0] >= 10)
        {
            Timer0_cnt[0] = 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[i]++;
    }
}

工程中文文件名报错,修改为英文即可。

6.4. 任务四:

任务四是在任务一的基础上加了基于定时器0实现的多任务系统架构,使得代码更加简洁高效。

#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[8] = {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();
}
#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[0]);

//任务状态标记函数,放在定时器1ms中断函数里面
void Task_Run_Time(void)
{
    uint8_t i;
    for(i=0;i<Task_Max;i++)//扫描每一个任务列表
    {
       if(My_Task[i].tim_cnt)//任务执行周期有值
       {
           My_Task[i].tim_cnt--;
           if(My_Task[i].tim_cnt == 0)//任务执行周期到了
           {
              My_Task[i].tim_cnt = My_Task[i].tim_newcnt;//重新赋值周期
              My_Task[i].task_state = 1;//标记任务可执行状态
           }
       }
    }
}

//任务回调函数处理
void Task_Callback_Handler(void)
{
   uint8_t i;
   for(i=0;i<Task_Max;i++)
   {
      if(My_Task[i].task_state)
      {
        My_Task[i].task_state = 0;
        My_Task[i].task_callback();
      }        
   }
}
#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;  
   }
}

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 16:05:37 | 显示全部楼层
27276*** 发表于 2024-12-16 12:29
贴主的笔记很详细,给你点个赞
希望你能继续坚持下去

谢谢
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:82
  • 最近打卡:2025-05-07 08:17:25
已绑定手机

2

主题

27

回帖

281

积分

中级会员

积分
281
发表于 2024-12-16 16:30:41 来自手机 | 显示全部楼层
KeilC251安装完,安装包按钮灰色啥原因
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-12-16 16:37:50
已绑定手机

1

主题

8

回帖

39

积分

新手上路

积分
39
发表于 2024-12-16 16:40:07 | 显示全部楼层
wamc*** 发表于 2024-12-16 16:30
KeilC251安装完,安装包按钮灰色啥原因

?截图看看
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-7 09:11 , Processed in 0.139883 second(s), 118 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表