找回密码
 立即注册
楼主: zhrxxhuy

利用普中A2开发板学习AI8051U的心得

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 4 天前 | 显示全部楼层
第十一期(第11集《矩阵按键》)

普中开发板上的是4X4的矩阵按键,代码编写如下。写的不是很优雅,但也算好用。


  1. u8 matrix_key(void)
  2. {
  3.         u8 key_num=0;
  4.         P13=0;P12=1;P11=1;P10=1;
  5.         if(P17==0)
  6.         {
  7.                 key_num=1;
  8.         }else if(P16==0)
  9.         {
  10.                 key_num=2;
  11.         }else if(P15==0)
  12.         {
  13.                 key_num=3;
  14.         }else if(P14==0)
  15.         {
  16.                 key_num=4;
  17.         }        
  18.         P13=1;P12=0;P11=1;P10=1;
  19.         if(P17==0)
  20.         {
  21.                 key_num=5;
  22.         }else if(P16==0)
  23.         {
  24.                 key_num=6;
  25.         }else if(P15==0)
  26.         {
  27.                 key_num=7;
  28.         }else if(P14==0)
  29.         {
  30.                 key_num=8;
  31.         }
  32.         P13=1;P12=1;P11=0;P10=1;
  33.         if(P17==0)
  34.         {
  35.                 key_num=9;
  36.         }else if(P16==0)
  37.         {
  38.                 key_num=10;
  39.         }else if(P15==0)
  40.         {
  41.                 key_num=11;
  42.         }else if(P14==0)
  43.         {
  44.                 key_num=12;
  45.         }
  46.         P13=1;P12=1;P11=1;P10=0;
  47.         if(P17==0)
  48.         {
  49.                 key_num=13;
  50.         }else if(P16==0)
  51.         {
  52.                 key_num=14;
  53.         }else if(P15==0)
  54.         {
  55.                 key_num=15;
  56.         }else if(P14==0)
  57.         {
  58.                 key_num=16;
  59.         }
  60.         return key_num;
  61. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 4 天前 | 显示全部楼层
第十二期(第12集《复位系统》)

这集视频比较全面地介绍了复位系统。注意到:
89C52的复位脚是高电平复位,而AI8051U是低电平复位,所以普中开发板上的复位按键不起作用,但好在擎天柱上的复位按键是可以用的。

另外,USB复位代码很重要,不然按复位之后,串口通讯将失效,printf打印不出东西来!

  1. //复位USB 很重要
  2.         P3M0 &=~0x03;
  3.         P3M1 |=0x03;       
  4.        
  5.         USBCON=0x00;
  6.         USBCLK=0x00;
  7.         IRC48MCR=0x00;
  8.         delay_ms(10);
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 3 天前 | 显示全部楼层
第十三期(第13集《外部中断》)

本来外部中断的难点是不记得哪些引脚支持,以及对应的中断向量号。不过幸好有ISP工具自动生成代码,所以用起来还比较顺。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 3 天前 | 显示全部楼层
第十四期(第14集《IO中断》)

由于Keil的中断向量号最高只能支持到31,所以需要下载插件来进一步拓展,或者通过保留的13号中断来路由。由于后者需要用到汇编语言(完全不懂),所以貌似还是前者更方便。
  1. ;P3的13号中断
  2.         ;CSEG AT 0143H
  3.         ;JMP P3INT_SR
  4. ;P3INT_SR:
  5.         ;JMP 006BH
  6.         ;END
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 前天 00:08 | 显示全部楼层
第十五期(第15集《定时器做计数器》)

定时器如果切换为计数器,就可以利用特定引脚计量输入的脉冲数,实现编码器测速等功能。

  1. #define COUNTER 10
  2. void Timer1_Init(void)                //计数器
  3. {
  4.         AUXR |= 0x40;                        //定时器时钟1T模式
  5.         TMOD &= 0x0F;                        //设置定时器模式为计数器
  6.         TMOD |= 0x40;
  7.         TL1 = (65536-COUNTER);                                //设置定时初始值
  8.         TH1 = (65536-COUNTER)>>8;                                //设置定时初始值
  9.         TF1 = 0;                                //清除TF1标志
  10.         
  11.         P3PU |=0x20;           //打开P3.5上拉电阻
  12.         
  13.         TR1 = 1;                                //定时器1开始计时
  14.         ET1 = 1;                                //使能定时器1中断
  15. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 前天 23:49 | 显示全部楼层
第十六期(第16集《DS18B20测温》)

这节课温习了一下单总线协议的写法。视频讲得很细,挺好的。
  1. #include "18B20.h"
  2. #include "io.h"
  3. u32 DS18B20_Temp=0;
  4. u8 minus=0;
  5. void Delay480us(void)        //@40.000MHz
  6. {
  7.         unsigned long edata i;
  8.         _nop_();
  9.         _nop_();
  10.         _nop_();
  11.         i = 4798UL;
  12.         while (i) i--;
  13. }
  14. void Delay60us(void)        //@40.000MHz
  15. {
  16.         unsigned long edata i;
  17.         _nop_();
  18.         _nop_();
  19.         _nop_();
  20.         i = 598UL;
  21.         while (i) i--;
  22. }
  23. void Delay1us(void)        //@40.000MHz
  24. {
  25.         unsigned long edata i;
  26.         _nop_();
  27.         _nop_();
  28.         _nop_();
  29.         i = 8UL;
  30.         while (i) i--;
  31. }
  32. void DS18B20_reset(void)
  33. {
  34.         u8 flag=1;
  35.         while(flag)
  36.         {
  37.                 DQ=0;
  38.                 Delay480us();
  39.                 DQ=1;
  40.                 Delay60us();
  41.                 flag=DQ;
  42.                 Delay480us();
  43.         }
  44. }
  45. void DS18B20_write_0(void)
  46. {
  47.         DQ=0;
  48.         Delay60us();
  49.         DQ=1;
  50.         Delay1us();
  51.         Delay1us();
  52. }
  53. void DS18B20_write_1(void)
  54. {
  55.         DQ=0;
  56.         Delay1us();
  57.         Delay1us();
  58.         DQ=1;
  59.         Delay60us();
  60. }
  61. bit DS18B20_read(void)
  62. {
  63.         bit b=0;
  64.         DQ=0;
  65.         Delay1us();
  66.         Delay1us();
  67.         DQ=1;
  68.         Delay1us();
  69.         Delay1us();
  70.         b=DQ;
  71.         Delay60us();
  72.         return b;
  73. }
  74. void DS18B20_write_byte(u8 dat)
  75. {
  76.         u8 i;
  77.         for(i=0;i<8;i++)
  78.         {
  79.                 if((dat>>i) & 0x01)
  80.                         DS18B20_write_1();
  81.                 else
  82.                         DS18B20_write_0();
  83.         }
  84. }
  85. u8 DS18B20_read_byte(void)
  86. {
  87.         u8 dat=0;
  88.         u8 i;
  89.         for(i=0;i<8;i++)
  90.         {
  91.                 dat >>= 1;
  92.                 if(DS18B20_read())
  93.                         dat |= 0x80;
  94.         }
  95.         return dat;
  96. }
  97. void DS18B20_ReadTemp(void)
  98. {
  99.         u8 datH=0, datL=0;
  100.         u16 temp=0;
  101. /* 发送检测命令 */        
  102.         DS18B20_reset();
  103.         DS18B20_write_byte(0xCC); //跳过ROM命令
  104.         DS18B20_write_byte(0x44); //开始转化
  105.         while(!DQ);
  106. /* 发送读取命令 */        
  107.         DS18B20_reset();
  108.         DS18B20_write_byte(0xCC); //跳过ROM命令
  109.         DS18B20_write_byte(0xBE); //开始读取
  110.         datL=DS18B20_read_byte();
  111.         datH=DS18B20_read_byte();
  112.         
  113.         if(datH & 0x80)
  114.         {
  115.                 minus=1;
  116.                 temp=((u16)datH<<8)|(u16)datL;
  117.                 temp =~temp+1; //负数取补码
  118.                 DS18B20_Temp=(u32)temp*625; //放大1万倍
  119.         }
  120.         else
  121.         {
  122.                 minus=0;
  123.                 temp=((u16)datH<<8)|(u16)datL;
  124.                 DS18B20_Temp=(u32)temp*625; //放大1万倍
  125.         }
  126. }
  127. void DS18B20_ShowTemp(u8 digit)
  128. {
  129.         u8 i;
  130.         u32 new_temp;
  131.         if(digit>4) digit=4;  //最多4为小数
  132.         new_temp=DS18B20_Temp/(u32)pow(10,4-digit);
  133.         for(i=0;i<digit+2;i++)
  134.         {        
  135.                 if(i==digit)
  136.                         digit_show((u8)(new_temp/(u32)pow(10,i)%10),(u8)(i+1),1);
  137.                 else
  138.                         digit_show((u8)(new_temp/(u32)pow(10,i)%10),(u8)(i+1),0);
  139.         }
  140. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-05-01 07:51:17
已绑定手机

2

主题

15

回帖

66

积分

注册会员

积分
66
发表于 7 小时前 | 显示全部楼层
第十七期(第17集《串口的简单应用》)
第十八期(第18集《串口高级应用》)

利用串口超时中断接收不定长数据非常实用。不过因为计算合适的超时时长还是比较复杂,所以干脆可以把时长设长一点。我一开始用AiCube自动配置的10个串口波特率时长会触发两次超时中断,延长到255个就好了。

  1. //<<AICUBE_USER_HEADER_REMARK_BEGIN>>
  2. ////////////////////////////////////////
  3. // 在此添加用户文件头说明信息
  4. // 文件名称: uart.c
  5. // 文件描述:
  6. // 文件版本: V1.0
  7. // 修改记录:
  8. //   1. (2025-04-30) 创建文件
  9. ////////////////////////////////////////
  10. //<<AICUBE_USER_HEADER_REMARK_END>>
  11. #include "config.h"
  12. //<<AICUBE_USER_INCLUDE_BEGIN>>
  13. // 在此添加用户头文件包含
  14. //<<AICUBE_USER_INCLUDE_END>>
  15. //<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
  16. u8 Rec_Dat[50];
  17. u8 Rec_Num=0;
  18. bit B_TX2_Busy=0;
  19. bit B_TX2_OK=0;
  20. //<<AICUBE_USER_GLOBAL_DEFINE_END>>
  21. ////////////////////////////////////////
  22. // 串口2中断服务程序
  23. // 入口参数: 无
  24. // 函数返回: 无
  25. ////////////////////////////////////////
  26. void UART2_ISR(void) interrupt UART2_VECTOR
  27. {
  28.     //<<AICUBE_USER_UART2_ISR_CODE1_BEGIN>>
  29.     // 在此添加中断函数用户代码
  30.     if (UART2_CheckTxFlag())            //判断串口发送中断
  31.     {
  32.         UART2_ClearTxFlag();            //清除串口发送中断标志
  33.                 B_TX2_Busy=0;
  34.     }
  35.     if (UART2_CheckRxFlag())            //判断串口接收中断
  36.     {
  37.         UART2_ClearRxFlag();            //清除串口接收中断标志
  38.                
  39.                 UR2TOCR = 0xe0;
  40.                
  41.                 Rec_Dat[Rec_Num++]=S2BUF;
  42.     }
  43.         
  44.         if(UR2TOSR & 0x01)
  45.         {
  46.                 B_TX2_OK = 1;
  47.                 UR2TOSR = 0;
  48.                 UR2TOCR = 0x00;
  49.         }
  50.     //<<AICUBE_USER_UART2_ISR_CODE1_END>>
  51. }
  52. ////////////////////////////////////////
  53. // 串口2初始化函数
  54. // 入口参数: 无
  55. // 函数返回: 无
  56. ////////////////////////////////////////
  57. void UART2_Init(void)
  58. {
  59. #ifdef BAUDRATE
  60. #undef BAUDRATE
  61. #endif
  62. #define BAUDRATE        (115200)
  63. #define T2_RELOAD       (65536 - (SYSCLK / BAUDRATE + 2) / 4)
  64.     UART2_SwitchP4243();                //设置串口数据端口: RxD2 (P4.2), TxD2 (P4.3)
  65. //  UART2_Timer2BRT();                  //串口2固定选择定时器2作为波特率发生器
  66.     TIMER2_TimerMode();                 //设置定时器2为定时模式
  67.     TIMER2_1TMode();                    //设置定时器2为1T模式
  68.     TIMER2_SetPrescale(0);              //设置定时器2的8位预分频
  69.     TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
  70.     TIMER2_Run();                       //定时器2开始运行
  71.     UART2_EnableRx();                   //使能串口2接收数据
  72.     UART2_Mode3();                      //设置串口2为模式3 (9位数据可变波特率)
  73.     UART2_OddParity();                  //串口2硬件自动奇校验
  74.     UART2_SetIntPriority(0);            //设置中断为最低优先级
  75.     UART2_EnableInt();                  //使能串口2中断
  76.     UART2_TimeoutScale_BRT();           //设置串口波特率为接收超时时间基准
  77.     UART2_SetTimeoutInterval(0x0000ff); //设置接收超时时间长度
  78.     UART2_EnableTimeoutInt();           //使能串口接收超时中断
  79.     UART2_EnableTimeout();              //使能串口接收超时功能
  80.     //<<AICUBE_USER_UART2_INITIAL_BEGIN>>
  81.     // 在此添加用户初始化代码
  82.     //<<AICUBE_USER_UART2_INITIAL_END>>
  83. }
  84. //<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
  85. void uart_receive(void)
  86. {
  87.         if(B_TX2_OK)
  88.         {
  89.                 B_TX2_OK=0;
  90.                 uart_send("receive finish\r\n");
  91.         }
  92.         if(Rec_Num>=6)
  93.         {
  94.                 if(Rec_Dat[Rec_Num-1]=='\n' && Rec_Dat[Rec_Num-2]=='\r')
  95.                 {
  96.                         if(Rec_Dat[Rec_Num-6]=='o' && Rec_Dat[Rec_Num-5]=='p'&& Rec_Dat[Rec_Num-4]=='e' && Rec_Dat[Rec_Num-3]=='n')
  97.                         {
  98.                                 P00=0;
  99.                                 uart_send("open\r\n");
  100.                         }
  101.                         if(Rec_Dat[Rec_Num-7]=='c' && Rec_Dat[Rec_Num-6]=='l' && Rec_Dat[Rec_Num-5]=='o'&& Rec_Dat[Rec_Num-4]=='s' && Rec_Dat[Rec_Num-3]=='e')
  102.                         {
  103.                                 P00=1;
  104.                                 uart_send("closed\r\n");
  105.                         }
  106.                         Rec_Num=0;
  107.                 }
  108.         }
  109. }
  110. void uart_send(u8 *dat)
  111. {
  112.         for(;*dat !=0; dat++)
  113.         {
  114.                 S2BUF=*dat;
  115.                 B_TX2_Busy=1;
  116.                 while(B_TX2_Busy);
  117.         }
  118. }
  119. //<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
复制代码



回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 17:54 , Processed in 0.128088 second(s), 79 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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