找回密码
 立即注册
楼主: yuyy***

冲哥32位8051视频学习日记-已看到27集-实验箱到了

[复制链接]
  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-14 16:21:32 | 显示全部楼层
    第15集,外部中断
    1.中断和中断系统
    手册里介绍了什么是中断和中断系统
    QQ截图20230514145001.png

    支持的中断源
    QQ截图20230514145130.png QQ截图20230514145154.png QQ截图20230514145207.png

    2.外部中断
    外部中断就是在单片机的一个引脚上,由于外部因素导致了一个电平的变化 (比如由高变低),而通过捕获这个变化,单片机内部自主运行的程序就会被暂时打断,转面去执行相应的中断处理程序,执行完后又回到原来中断的地方继续执行原来的程序。
    INT0-INT4的中断号
    QQ截图20230514152831.png

    测试例程
    1. #include "config.h"
    2. //USB调试及复位所需定义
    3. char *USER_DEVICEDESC = NULL;
    4. char *USER_PRODUCTDESC = NULL;
    5. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    6. void test_int0(void) interrupt 0 //INT0 P3.2可触发
    7. {
    8.     P20 = !P20;
    9. }
    10. void test_int1(void) interrupt 2 //INT1 P3.3可触发
    11. {
    12.     P21 = !P21;
    13. }
    14. void test_int2(void) interrupt 10 //INT2 P3.6可触发
    15. {
    16.     P22 = !P22;
    17. }
    18. void test_int3(void) interrupt 11 //INT3 P3.7可触发
    19. {
    20.     P23 = !P23;
    21. }
    22. void test_int4(void) interrupt 16 //INT4 P3.0可触发
    23. {
    24.     P24 = !P24;
    25. }
    26. /******************** 主函数 **************************/
    27. void main(void)
    28. {
    29.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    30.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    31.     CKCON = 0; //提高访问XRAM速度
    32.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    33.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    34.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    35.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    36.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    37.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    38.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    39.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    40.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    41.     //USB调试及复位所需代码-----
    42.     P3M0 &= ~0x03;
    43.     P3M1 |= 0x03;
    44.     IRC48MCR = 0x80;
    45.     while (!(IRC48MCR & 0x01));
    46.     usb_init();
    47.     //-------------------------
    48.     IE0  = 0;   //外中断0标志位
    49.     IE1  = 0;   //外中断1标志位
    50.     EX0 = 1;    //INT0 使能
    51.     EX1 = 1;    //INT1 使能
    52.     EX2 = 1;    //INT2 使能
    53.     EX3 = 1;    //INT3 使能
    54.     EX4 = 1;    //INT4 使能
    55.     IT0 = 1;        //INT0 下降沿中断      
    56.     IT1 = 1;        //INT1 下降沿中断      
    57.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    58.     EA = 1;     //打开总中断
    59.     LED0 = 1;
    60.    
    61.     printf_hid("STC32G 测试程序\r\n");
    62.     while(1)
    63.     {
    64.     }
    65. }
    复制代码
    在外部触发某个需要及时处理的事件时又不能频繁轮询IO状态时需要用到外部中断,例如一些使用电池供电的设备处理按键或者获取传感器数据,由于低功耗的要求不能像以前课程里那样每10ms查询一次IO状态



    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-16 16:49:43 | 显示全部楼层
    第16集,IO中断

    QQ截图20230514163808.png

    外部中断只有指定的几个IO口可以触发,IO中断所有的IO都能触发,屠龙刀三.2可以使用下降沿中断

    Keil的中断号有限制,可以借助工具扩展Keil的中断号

    QQ截图20230516151434.png

    IO中断配置需要用到的寄存器
    QQ截图20230514163857.png QQ截图20230514171612.png

    各端口使用的中断号
    QQ截图20230516152338.png

    演示代码,没有数码管只能使用虚拟数码管

    1. uint16_t timercount = 0;
    2. uint8_t seg0num = 0;
    3. uint8_t seg1num = 0;
    4. void test_usbseg()
    5. {
    6.     uint8_t segdatas[8]={0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
    7.     segdatas[0] = ledsegcodes[seg0num];
    8.     segdatas[1] = ledsegcodes[seg1num];
    9.     SEG7_ShowCode(segdatas);
    10. }
    11. void test_timer0_cb(void)
    12. {
    13.     if(timercount < 50)
    14.     {
    15.         timercount++;
    16.     }
    17.     else
    18.     {
    19.         timercount = 0;
    20.         test_usbseg();
    21.     }
    22. }
    23. void test_P3int(void) interrupt 40 //P3端口IO中断
    24. {
    25.     uint8_t intf;
    26.     intf = P3INTF;
    27.     if(intf)
    28.     {
    29.         P3INTF = 0;//清除中断标识
    30.         if(intf&0x20) //P35产生中断
    31.         {
    32.             seg0num++;
    33.             if(seg0num > 9)
    34.                 seg0num = 0;
    35.         }
    36.     }
    37. }
    38. /******************** 主函数 **************************/
    39. void main(void)
    40. {
    41.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    42.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    43.     CKCON = 0; //提高访问XRAM速度
    44.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    45.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    46.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    47.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    48.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    49.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    50.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    51.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    52.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    53.     //USB调试及复位所需代码-----
    54.     P3M0 &= ~0x03;
    55.     P3M1 |= 0x03;
    56.     IRC48MCR = 0x80;
    57.     while (!(IRC48MCR & 0x01));
    58.     usb_init();
    59.     //-------------------------
    60.     P3IM0 = 0x00;
    61.     P3IM1 = 0x00; //P35下降沿中断,屠龙刀三.2可以使用下降沿中断
    62.     P3INTE = 0x20; //P35中断使能
    63.     P5IM0 = 0x00;
    64.     P5IM1 = 0x00;//P54下降沿中断,屠龙刀三.2可以使用下降沿中断
    65.     P5INTE = 0x10;//P54中断使能
    66.     PIN_IPH = 0x00;
    67.     PIN_IP = 0x20; //P5端口设置优先级1
    68.    
    69.     yuyy_timer0init(10000,test_timer0_cb); //10ms定时
    70.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    71.     EA = 1;     //打开总中断
    72.     while(1)
    73.     {
    74.     }
    75. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-17 10:43:02 | 显示全部楼层
    第17集,模数转换器ADC
    模数转换器即 A/D 转换器,或简称 ADC(Analog-to-digital converter),通常是指一个将模拟信号转变为数字信号的电子元件。
    各通道对应IO
    QQ截图20230516224947.png

    计算公式
    QQ截图20230517102744.png

    QQ截图20230517102757.png

    演示代码
    1. //USB调试及复位所需定义
    2. char *USER_DEVICEDESC = NULL;
    3. char *USER_PRODUCTDESC = NULL;
    4. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    5. void delay_ms(uint16_t ms)
    6. {
    7.     uint16_t i;
    8.     do{
    9.         i = MAIN_Fosc / 6000;
    10.         while(--i);   //6T per loop
    11.     }while(--ms);
    12. }
    13. /******************** 主函数 **************************/
    14. void main(void)
    15. {
    16.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    17.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    18.     CKCON = 0; //提高访问XRAM速度
    19.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    20.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    21.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    22.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    23.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    24.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    25.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    26.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    27.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    28.     //USB调试及复位所需代码-----
    29.     P3M0 &= ~0x03;
    30.     P3M1 |= 0x03;
    31.     IRC48MCR = 0x80;
    32.     while (!(IRC48MCR & 0x01));
    33.     usb_init();
    34.     //-------------------------
    35.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    36.     EA = 1;     //打开总中断
    37.     P1M0 = 0x00;
    38.     P1M1 = 0x01;   //P1.0高阻输入,作为ADC的引脚必须设置为高阻输入
    39.     ADCTIM = 0x3F; //设置ADC内部时序
    40.     ADCCFG = 0x2F; //结果右对齐,设置ADC时钟为系统时钟/2/16
    41.     ADC_POWER = 1; //使能ADC模块
    42.     ADC_CONTR &= 0xF0; //选择通道0;
    43.     while(1)
    44.     {
    45.         uint16_t adcresult;
    46.         float adcv;
    47.         ADC_START = 1;//启动ADC转换
    48.         _nop_();
    49.         _nop_();
    50.         _nop_();
    51.         while(ADC_FLAG == 0);   //wait for ADC finish
    52.         ADC_FLAG = 0;     //清除ADC结束标志
    53.         adcresult = (ADC_RES<<8)&0x0F00;
    54.         adcresult |= ADC_RESL;
    55.         adcv = 5.0*adcresult/4096; //计算为电压
    56.         printf_hid("ADC结果: 0x%03X ADC电压: %.2fV\r\n",adcresult,adcv);
    57.         delay_ms(1000);
    58.     }
    59. }
    复制代码
    没有2.5v的电压源,通过杜邦线将Vref连接到VCC,P1.0接一个从USB转串口引出来的3.3v,与屠龙刀开发板共地,运行截图
    QQ截图20230517103349.png

    比万用表测得电压高0.08V左右

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-17 20:41:40 | 显示全部楼层
    第18集,ADC采集电源电压和ADC按键上
    利用ADC测量VCC供电电压
    演示代码
    1. #define VREFH_ADDR CHIPID7
    2. #define VREFL_ADDR CHIPID8
    3. bit busy;
    4. int BGV;
    5. //USB调试及复位所需定义
    6. char *USER_DEVICEDESC = NULL;
    7. char *USER_PRODUCTDESC = NULL;
    8. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    9. void delay_ms(uint16_t ms)
    10. {
    11.     uint16_t i;
    12.     do{
    13.         i = MAIN_Fosc / 6000;
    14.         while(--i);   //6T per loop
    15.     }while(--ms);
    16. }
    17. void ADCInit()
    18. {
    19.     ADCTIM = 0x3F;   //设置 ADC 内部时序
    20.     ADCCFG = 0x2F;   //结果右对齐,设置 ADC 时钟为系统时钟/2/16
    21.     ADC_CONTR = 0x8F; //使能 ADC 模块,并选择第 15 通道
    22. }
    23. int ADCRead()
    24. {
    25.     int res;
    26.     ADC_START = 1; //启动 AD 转换
    27.     _nop_();
    28.     _nop_();
    29.     while (!ADC_FLAG); //查询 ADC 完成标志
    30.     ADC_FLAG = 0; //清完成标志
    31.     res = (ADC_RES << 8) | ADC_RESL; //读取 ADC 结果
    32.     return res;
    33. }
    34. /******************** 主函数 **************************/
    35. void main(void)
    36. {
    37.     int res;
    38.     int vcc;
    39.     int i;
    40.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    41.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    42.     CKCON = 0; //提高访问XRAM速度
    43.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    44.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    45.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    46.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    47.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    48.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    49.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    50.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    51.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    52.     //USB调试及复位所需代码-----
    53.     P3M0 &= ~0x03;
    54.     P3M1 |= 0x03;
    55.     IRC48MCR = 0x80;
    56.     while (!(IRC48MCR & 0x01));
    57.     usb_init();
    58.     //-------------------------
    59.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    60.     EA = 1;     //打开总中断
    61.     BGV = (VREFH_ADDR << 8) + VREFL_ADDR; //从 CHIPID 中读取内部参考电压值
    62.     ADCInit(); //ADC 初始化
    63.     ADCRead();
    64.     ADCRead();//前两个数据建议丢弃
    65.     while(1)
    66.     {
    67.         res = 0;
    68.         for (i=0; i<8; i++)
    69.         {
    70.             res += ADCRead(); //读取 8 次数据
    71.         }
    72.         res >>= 3; //取平均值
    73.         vcc = (int)(4096L * BGV / res); //(12 位 ADC 算法)计算 VREF 管脚电压,即电池电压 注意,此电压的单位为毫伏(mV)
    74.         printf_hid("VCC电压:%dmv\r\n",vcc);
    75.         delay_ms(1000);
    76.     }
    77. }
    复制代码
    Vref连接到VCC,USB供电,测量结果

    QQ截图20230517142346.png


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-18 17:40:21 | 显示全部楼层
    第18集,ADC采集电源电压和ADC按键中
    ADC按键,按下按键时,通过电阻分压得到不同的电压值,ADC采集在各个范围内的值来判定是哪个按键按下
    优点是只需要一个IO就能实现多个按键的识别
    缺点是识别精度差,不能识别同时按下多个按键,程序要一直保持扫描来识别按键按下
    示例代码,和之前的普通按键和矩阵按键集成到一起了,因为没有ADC按键所以ADC按键部分未经验证
    yuyy_key.h
    1. #ifndef __YUYY_KEY_H_
    2. #define __YUYY_KEY_H_
    3. #include "config.h"
    4. #define KEYSCANINTERVAL 10//按键扫描间隔
    5. #define DEBOUNCETIME 30 //去抖时间
    6. #define LONGPRESSTIME 2000 //长按识别时间
    7. //普通按键
    8. #define GPIOKEYNUMS 4 //按键总数
    9. #define KEYPORT P3 //按键io端口号
    10. #define KEYIOSTART 2 //按键io起始值 屠龙刀的按键从P3.2开始
    11. #define KEYDOWNLEV 0 //按键按下的io电平
    12. //矩阵按键
    13. #define MATRIXKEYCOLS 4 //按键列数
    14. #define MATRIXKEYROWS 2 //按键行数
    15. #define MATRIXKEYNUMS MATRIXKEYCOLS*MATRIXKEYROWS //矩阵按键总数
    16. /**
    17. *按键分布示例
    18. *     P00 P01 P02 P03
    19. * P06  0   1   2   3
    20. * P07  4   5   6   7   
    21. */
    22. #define MATRIXKEYROW0PIN P06 //第0行IO
    23. #define MATRIXKEYROW1PIN P07 //第1行IO
    24. #define MATRIXKEYCOL0PIN P00 //第0列IO
    25. #define MATRIXKEYCOL1PIN P01 //第1列IO
    26. #define MATRIXKEYCOL2PIN P02 //第2列IO
    27. #define MATRIXKEYCOL3PIN P03 //第3列IO
    28. //ADC按键
    29. #define ADCKEYNUMS 16  //ADC按键总数
    30. #define ADCKEYPIN P10 //ADC按键io
    31. #define ADCKEYCHANNEL 0//
    32. #define ADCKEYOFFSET 64//允许的误差值
    33. enum YUYY_KEYSTATE
    34. {
    35.     KEY_UP = 0,      //按键未按下
    36.     KEY_DOWN,        //按键按下
    37.     KEY_SINGLECLICK, //单击按键 按下按键后在LONGPRESSTIME之前松开
    38.     KEY_LONGPRESS,   //长按按键 按下按键的时间超过LONGPRESSTIME
    39.     KEY_LONGPRESSUP  //长按后松开
    40. };
    41. enum YUYY_KEYTYPE
    42. {
    43.     KEYTYPE_GPIO = 0,      //普通按键
    44.     KEYTYPE_MATRIX,        //矩阵按键
    45.     KEYTYPE_ADC,           //ADC按键
    46. };
    47. //定义回调
    48. typedef void (*yuyy_key_cb)(enum YUYY_KEYTYPE keytype,uint8_t keynum,enum YUYY_KEYSTATE state);
    49. /**
    50. * 初始化按键,设置回调函数
    51. * 外部文件通过回调函数监控按键状态
    52. */
    53. void yuyy_keyinit(yuyy_key_cb cb);
    54. /**
    55. * 10ms一次检查按键状态
    56. */
    57. void yuyy_keyloop(void);
    58. #endif
    复制代码
    yuyy_key.c
    1. #include "yuyy_key.h"
    2. #include "yuyy_delay.h"
    3. #if(GPIOKEYNUMS)
    4. uint16_t gpiokeydowncount[GPIOKEYNUMS] = {0};
    5. #else
    6. uint16_t gpiokeydowncount[1] = {0};
    7. #endif
    8. #if(MATRIXKEYNUMS)
    9. uint16_t matrixkeydowncount[MATRIXKEYNUMS] = {0};
    10. #else
    11. uint16_t matrixkeydowncount[1] = {0};
    12. #endif
    13. #if(ADCKEYNUMS)
    14. uint16_t adckeydowncount[ADCKEYNUMS] = {0};
    15. #else
    16. uint16_t adckeydowncount[1] = {0};
    17. #endif
    18. uint16_t adcperkey;
    19. yuyy_key_cb keycb;
    20. void sendkeystate(enum YUYY_KEYTYPE keytype,uint8_t keynum,enum YUYY_KEYSTATE state)
    21. {
    22.     if(keycb)
    23.     {
    24.         keycb(keytype,keynum,state);
    25.     }
    26. }
    27. void yuyy_refreshkey(enum YUYY_KEYTYPE keytype,uint8_t key,uint8_t down)
    28. {
    29.     uint16_t *keydowncount;
    30.     if(keytype == KEYTYPE_GPIO)
    31.     {
    32.         keydowncount = gpiokeydowncount;
    33.     }
    34.     else if(keytype == KEYTYPE_MATRIX)
    35.     {
    36.         keydowncount = matrixkeydowncount;
    37.     }
    38.     else if(keytype == KEYTYPE_ADC)
    39.     {
    40.         keydowncount = adckeydowncount;
    41.     }
    42.     else
    43.     {
    44.         return;
    45.     }
    46.     if(down)
    47.     {
    48.         if(keydowncount[key] < 0xFFFF)
    49.         {
    50.             keydowncount[key]++;
    51.         }
    52.         if(keydowncount[key]*KEYSCANINTERVAL == DEBOUNCETIME)
    53.         {
    54.             sendkeystate(keytype,key,KEY_DOWN);
    55.         }
    56.         if(keydowncount[key]*KEYSCANINTERVAL == LONGPRESSTIME)
    57.         {
    58.             sendkeystate(keytype,key,KEY_LONGPRESS);
    59.         }
    60.     }
    61.     else
    62.     {
    63.         if(keydowncount[key]*KEYSCANINTERVAL > DEBOUNCETIME)
    64.         {
    65.             if(keydowncount[key]*KEYSCANINTERVAL < LONGPRESSTIME)
    66.             {
    67.                 sendkeystate(keytype,key,KEY_SINGLECLICK);
    68.             }
    69.             else
    70.             {
    71.                 sendkeystate(keytype,key,KEY_LONGPRESSUP);
    72.             }
    73.         }
    74.         keydowncount[key] = 0;
    75.     }
    76. }
    77. void yuyy_gpiokeyloop(void)
    78. {
    79.     uint8_t key = 0;
    80.     while (key<GPIOKEYNUMS)
    81.     {
    82.         if(((KEYPORT >> (key+KEYIOSTART)) & 0x01) == KEYDOWNLEV)
    83.         {
    84.             yuyy_refreshkey(KEYTYPE_GPIO,key,1);
    85.         }
    86.         else
    87.         {
    88.             yuyy_refreshkey(KEYTYPE_GPIO,key,0);
    89.         }
    90.         key++;
    91.     }
    92. }
    93. void yuyy_matrixkeyloop(void)
    94. {
    95.     uint8_t key = 0;
    96.     uint8_t i,j,col = 0,row = 0;
    97.     MATRIXKEYROW0PIN = 1;
    98.     MATRIXKEYROW1PIN = 1;
    99.     MATRIXKEYCOL0PIN = 0;
    100.     MATRIXKEYCOL1PIN = 0;
    101.     MATRIXKEYCOL2PIN = 0;
    102.     MATRIXKEYCOL3PIN = 0;
    103.     yuyy_delay_us(10);
    104.     if (MATRIXKEYROW0PIN == 0)
    105.     {
    106.         row |= 0x01;
    107.     }
    108.     if (MATRIXKEYROW1PIN == 0)
    109.     {
    110.         row |= 0x02;
    111.     }
    112.     MATRIXKEYROW0PIN = 0;
    113.     MATRIXKEYROW1PIN = 0;
    114.     MATRIXKEYCOL0PIN = 1;
    115.     MATRIXKEYCOL1PIN = 1;
    116.     MATRIXKEYCOL2PIN = 1;
    117.     MATRIXKEYCOL3PIN = 1;
    118.     yuyy_delay_us(10);
    119.     if (MATRIXKEYCOL0PIN == 0)
    120.     {
    121.         col |= 0x01;
    122.     }
    123.     if (MATRIXKEYCOL1PIN == 0)
    124.     {
    125.         col |= 0x02;
    126.     }
    127.     if (MATRIXKEYCOL2PIN == 0)
    128.     {
    129.         col |= 0x04;
    130.     }
    131.     if (MATRIXKEYCOL3PIN == 0)
    132.     {
    133.         col |= 0x08;
    134.     }
    135.     MATRIXKEYROW0PIN = 1;
    136.     MATRIXKEYROW1PIN = 1;
    137.     MATRIXKEYCOL0PIN = 1;
    138.     MATRIXKEYCOL1PIN = 1;
    139.     MATRIXKEYCOL2PIN = 1;
    140.     MATRIXKEYCOL3PIN = 1;
    141.     for(i=0;i<MATRIXKEYROWS;i++)
    142.     {
    143.         for (j = 0; j < MATRIXKEYCOLS; j++)
    144.         {
    145.             if((row&(1<<i)) && (col&(1<<j)))
    146.             {
    147.                 yuyy_refreshkey(KEYTYPE_MATRIX,key,1);
    148.             }
    149.             else
    150.             {
    151.                 yuyy_refreshkey(KEYTYPE_MATRIX,key,0);
    152.             }
    153.             key++;
    154.         }
    155.         
    156.     }
    157. }
    158. uint16_t yuyy_readadc(uint8_t channel)
    159. {
    160.     uint16_t res;
    161.     ADC_CONTR &= 0xF0;
    162.     ADC_CONTR |= (channel&0x0F);
    163.     ADC_START = 1; //启动 AD 转换
    164.     _nop_();
    165.     _nop_();
    166.     while (!ADC_FLAG); //查询 ADC 完成标志
    167.     ADC_FLAG = 0; //清完成标志
    168.     res = ((ADC_RES << 8)&0x0F00) | ADC_RESL; //读取 ADC 结果
    169.     return res;
    170. }
    171. void yuyy_adcKeyloop(void)
    172. {
    173.     uint16_t keyadc,key = 0,adccmp = adcperkey;
    174.     keyadc = yuyy_readadc(ADCKEYCHANNEL);
    175.     while (key < ADCKEYNUMS)
    176.     {
    177.         if(keyadc>=adccmp-ADCKEYOFFSET && keyadc<adccmp+ADCKEYOFFSET)
    178.         {
    179.             //按键按下
    180.             yuyy_refreshkey(KEYTYPE_ADC,key,1);
    181.         }
    182.         else
    183.         {
    184.             //按键未按下
    185.             yuyy_refreshkey(KEYTYPE_ADC,key,0);
    186.         }
    187.         key++;
    188.         adccmp += adcperkey;
    189.     }
    190. }
    191. void yuyy_keyloop(void)
    192. {
    193.     #if(GPIOKEYNUMS)
    194.     yuyy_gpiokeyloop();
    195.     #endif
    196.     #if(MATRIXKEYNUMS)
    197.     yuyy_matrixkeyloop();
    198.     #endif
    199.     #if(ADCKEYNUMS)
    200.     yuyy_adcKeyloop();
    201.     #endif
    202. }
    203. void yuyy_adcKeyinit(void)
    204. {
    205.     P1M0 = 0x00;
    206.     P1M1 = 0x01;   //P1.0高阻输入,作为ADC的引脚必须设置为高阻输入
    207.     ADCTIM = 0x3F; //设置ADC内部时序
    208.     ADCCFG = 0x2F; //结果右对齐,设置ADC时钟为系统时钟/2/16
    209.     ADC_POWER = 1;
    210.     adcperkey = 4096/ADCKEYNUMS;
    211. }
    212. void yuyy_keyinit(yuyy_key_cb cb)
    213. {
    214.     #if(ADCKEYNUMS)
    215.     yuyy_adcKeyinit();
    216.     #endif
    217.     keycb = cb;
    218. }
    复制代码
    main.c
    1. #include "config.h"
    2. #include "string.h"
    3. #include "yuyy.h"
    4. //USB调试及复位所需定义
    5. char *USER_DEVICEDESC = NULL;
    6. char *USER_PRODUCTDESC = NULL;
    7. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    8. void test_timer0cb(void)
    9. {
    10.     yuyy_keyloop();
    11. }
    12. void test_keycb(enum YUYY_KEYTYPE keytype,uint8_t keynum,enum YUYY_KEYSTATE state)
    13. {
    14.     printf("按键类型:%d 按键号:%d 按键行为:%d\r\n",keytype,keynum,state);
    15. }
    16. /******************** 主函数 **************************/
    17. void main(void)
    18. {
    19.     int res;
    20.     int vcc;
    21.     int i;
    22.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    23.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    24.     CKCON = 0; //提高访问XRAM速度
    25.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    26.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    27.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    28.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    29.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    30.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    31.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    32.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    33.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    34.     //USB调试及复位所需代码-----
    35.     P3M0 &= ~0x03;
    36.     P3M1 |= 0x03;
    37.     IRC48MCR = 0x80;
    38.     while (!(IRC48MCR & 0x01));
    39.     //如果使用USB-CDC需要下面的两行代码
    40.     USBCLK = 0x00;
    41.     USBCON = 0x90;
    42.     //如果使用USB-HID注释掉上面两行代码
    43.     usb_init();
    44.     //-------------------------
    45.     yuyy_timer0init(10000,test_timer0cb); //10ms触发一次回调
    46.     yuyy_keyinit(test_keycb);
    47.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    48.     EA = 1;     //打开总中断
    49.     while(1)
    50.     {
    51.     }
    52. }
    复制代码
    只验证了普通按键和矩阵按键的工作情况
    QQ截图20230518173900.png


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-19 19:45:35 | 显示全部楼层
    第18集,ADC采集电源电压和ADC按键下
    没有ADC键盘,用屠龙刀上的P32-P354个按键做了个时钟,用P20上的LED模拟蜂鸣器,USB-CDC模拟数码管显示
    P32 长按进入时钟设置,短按设置位右移
    P33 点击改变数字,长按自动增加数字
    P34 长按设置闹钟,短按设置位左移
    P25 点击退出设置
    运行效果



    代码实现

    1. #include "config.h"
    2. #include "string.h"
    3. #include "yuyy.h"
    4. //USB调试及复位所需定义
    5. char *USER_DEVICEDESC = NULL;
    6. char *USER_PRODUCTDESC = NULL;
    7. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    8. const uint8_t ledsegcodes[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
    9. uint8_t clock10ms = 0; //毫秒
    10. uint8_t clocksec = 0; //秒
    11. uint8_t clockmin = 0; //分
    12. uint8_t clockhour = 0; //时
    13. uint8_t alertsec = 30; //闹钟秒
    14. uint8_t alertmin = 0; //闹钟分
    15. uint8_t alerthour = 0; //闹钟时
    16. uint8_t settingmode = 0; // 1配置时钟 2配置闹钟
    17. uint8_t settingpos = 0; //配置的数码管位
    18. uint8_t settingtimechanged = 0;
    19. uint8_t settingautoaddtimecount = 0;
    20. uint8_t settingautoadd = 0;
    21. uint8_t settingclock10ms = 0;
    22. void test_showclock(void)
    23. {
    24.     uint8_t segdatas[8]={0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00};
    25.     segdatas[7] = ledsegcodes[clocksec % 10];
    26.     segdatas[6] = ledsegcodes[clocksec / 10];
    27.     segdatas[4] = ledsegcodes[clockmin % 10];
    28.     segdatas[3] = ledsegcodes[clockmin / 10];
    29.     segdatas[1] = ledsegcodes[clockhour % 10];
    30.     segdatas[0] = ledsegcodes[clockhour / 10];
    31.     SEG7_ShowCode(segdatas);
    32. }
    33. void test_showclocksetting(void)
    34. {
    35.     uint8_t segdatas[8]={0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00};
    36.     if(settingmode == 1)
    37.     {
    38.         segdatas[7] = ledsegcodes[clocksec % 10];
    39.         segdatas[6] = ledsegcodes[clocksec / 10];
    40.         segdatas[4] = ledsegcodes[clockmin % 10];
    41.         segdatas[3] = ledsegcodes[clockmin / 10];
    42.         segdatas[1] = ledsegcodes[clockhour % 10];
    43.         segdatas[0] = ledsegcodes[clockhour / 10];
    44.     }
    45.     else if(settingmode == 2)
    46.     {
    47.         segdatas[7] = ledsegcodes[alertsec % 10];
    48.         segdatas[6] = ledsegcodes[alertsec / 10];
    49.         segdatas[4] = ledsegcodes[alertmin % 10];
    50.         segdatas[3] = ledsegcodes[alertmin / 10];
    51.         segdatas[1] = ledsegcodes[alerthour % 10];
    52.         segdatas[0] = ledsegcodes[alerthour / 10];
    53.     }
    54.     if(settingclock10ms == 0)
    55.     {
    56.         segdatas[settingpos] = 0x00;
    57.         SEG7_ShowCode(segdatas);
    58.     }
    59.     else if(settingclock10ms == 50)
    60.     {
    61.         SEG7_ShowCode(segdatas);
    62.     }
    63.     if(settingtimechanged)
    64.     {
    65.         if(settingclock10ms < 50)
    66.             segdatas[settingpos] = 0x00;
    67.         SEG7_ShowCode(segdatas);
    68.         settingtimechanged = 0;
    69.     }
    70.     if(settingclock10ms < 100)
    71.         settingclock10ms++;
    72.     else
    73.         settingclock10ms = 0;
    74. }
    75. void test_settingposright(void)
    76. {
    77.     if(settingpos == 0)
    78.     {
    79.         if(settingmode == 1 && clockhour > 23)
    80.         {
    81.             clockhour = 23;
    82.         }
    83.         else if(settingmode == 2 && alerthour > 23)
    84.         {
    85.             alerthour = 23;
    86.         }
    87.         settingpos = 1;
    88.     }
    89.     else if(settingpos == 1)
    90.         settingpos = 3;
    91.     else if(settingpos == 3)
    92.         settingpos = 4;
    93.     else if(settingpos == 4)
    94.         settingpos = 6;
    95.     else if(settingpos == 6)
    96.         settingpos = 7;
    97.     else
    98.         settingpos = 0;
    99.     settingtimechanged = 1;
    100. }
    101. void test_settingposleft(void)
    102. {
    103.     if(settingpos == 0)
    104.     {
    105.         if(settingmode == 1 && clockhour > 23)
    106.         {
    107.             clockhour = 23;
    108.         }
    109.         else if(settingmode == 2 && alerthour > 23)
    110.         {
    111.             alerthour = 23;
    112.         }
    113.         settingpos = 7;
    114.     }
    115.     else if(settingpos == 1)
    116.         settingpos = 0;
    117.     else if(settingpos == 3)
    118.         settingpos = 1;
    119.     else if(settingpos == 4)
    120.         settingpos = 3;
    121.     else if(settingpos == 6)
    122.         settingpos = 4;
    123.     else
    124.         settingpos = 6;
    125.     settingtimechanged = 1;
    126. }
    127. void test_settingadd(void)
    128. {
    129.     uint8_t setnum = 0;
    130.     uint8_t *times,*timem,*timeh;
    131.     if(settingmode == 1)
    132.     {
    133.         times = &clocksec;
    134.         timem = &clockmin;
    135.         timeh = &clockhour;
    136.     }
    137.     else if(settingmode == 2)
    138.     {
    139.         times = &alertsec;
    140.         timem = &alertmin;
    141.         timeh = &alerthour;
    142.     }
    143.     if(settingpos == 0)
    144.     {
    145.         setnum = *timeh/10;
    146.         setnum++;
    147.         if(setnum > 2)
    148.         {
    149.             setnum = 0;
    150.         }
    151.         *timeh = setnum*10 + *timeh%10;
    152.     }
    153.     else if(settingpos == 1)
    154.     {
    155.         setnum = *timeh%10;
    156.         *timeh -= setnum;
    157.         setnum++;
    158.         if(*timeh > 19)
    159.         {
    160.             if(setnum > 3)
    161.                 setnum = 0;
    162.         }
    163.         else if(setnum > 9)
    164.             setnum = 0;
    165.         *timeh = setnum + *timeh;
    166.     }
    167.     else if(settingpos == 3)
    168.     {
    169.         setnum = *timem/10;
    170.         setnum++;
    171.         if(setnum > 5)
    172.             setnum = 0;
    173.         *timem = setnum*10 + *timem%10;
    174.     }
    175.     else if(settingpos == 4)
    176.     {
    177.         setnum = *timem%10;
    178.         *timem -= setnum;
    179.         setnum++;
    180.         if(setnum > 9)
    181.             setnum = 0;
    182.         *timem = setnum + *timem;
    183.     }
    184.     else if(settingpos == 6)
    185.     {
    186.         setnum = *times/10;
    187.         setnum++;
    188.         if(setnum > 5)
    189.             setnum = 0;
    190.         *times = setnum*10 + *times%10;
    191.     }
    192.     else if(settingpos == 7)
    193.     {
    194.         setnum = *times%10;
    195.         *times -= setnum;
    196.         setnum++;
    197.         if(setnum > 9)
    198.             setnum = 0;
    199.         *times = setnum + *times;
    200.     }
    201.     settingtimechanged = 1;
    202.     settingclock10ms = 50;
    203. }
    204. void test_clockadd10ms(void)
    205. {
    206.     uint8_t timechanged = 0;
    207.     if(clock10ms < 100)
    208.         clock10ms++;
    209.     else
    210.     {
    211.         clock10ms = 0;
    212.         clocksec++;
    213.         timechanged = 1;
    214.     }
    215.     if(clocksec == 60)
    216.     {
    217.         clocksec = 0;
    218.         clockmin++;
    219.     }
    220.     if(clockmin == 60)
    221.     {
    222.         clockmin = 0;
    223.         clockhour++;
    224.     }
    225.     if(clockhour == 24)
    226.         clockhour = 0;
    227.     if(timechanged)
    228.     {
    229.         if(settingmode == 0)
    230.             test_showclock();
    231.         if(clocksec == alertsec && clockmin == alertmin && clockhour == alerthour)
    232.         {
    233.             yuyy_beep(300);
    234.         }
    235.     }
    236. }
    237. void test_timer0cb(void)
    238. {
    239.     if(settingmode == 0)
    240.         test_clockadd10ms();
    241.     else
    242.     {
    243.         if(settingautoadd)
    244.         {
    245.             if(settingautoaddtimecount < 25)
    246.             {
    247.                 settingautoaddtimecount++;
    248.             }
    249.             else
    250.             {
    251.                 settingautoaddtimecount = 0;
    252.                 test_settingadd();
    253.             }
    254.         }
    255.         test_showclocksetting();
    256.         if(settingmode == 2) //设置闹钟时时间正常走
    257.         {
    258.             test_clockadd10ms();
    259.         }
    260.     }
    261.     yuyy_keyloop();
    262.     yuyy_beep_loop();
    263. }
    264. void test_keycb(enum YUYY_KEYTYPE keytype,uint8_t keynum,enum YUYY_KEYSTATE state)
    265. {
    266.     if(keytype == KEYTYPE_GPIO)
    267.     {
    268.         switch (keynum)
    269.         {
    270.         case 0://P32
    271.             if(state == KEY_LONGPRESS)
    272.             {
    273.                 //长按进入配置,时钟暂停
    274.                 settingmode = 1;
    275.                 settingpos = 0;
    276.                 settingclock10ms = 0;
    277.             }
    278.             else if(state == KEY_SINGLECLICK)
    279.             {
    280.                 if(settingmode)
    281.                 {
    282.                     test_settingposright();//右移1位
    283.                 }
    284.             }
    285.             break;
    286.         case 1://P33
    287.             if(state == KEY_SINGLECLICK)
    288.             {
    289.                 //点击增加数字
    290.                 test_settingadd();
    291.             }
    292.             else if(state == KEY_LONGPRESS)
    293.             {
    294.                 settingautoaddtimecount = 0;
    295.                 settingautoadd = 1;
    296.             }
    297.             else if(state == KEY_LONGPRESSUP)
    298.             {
    299.                 settingautoaddtimecount = 0;
    300.                 settingautoadd = 0;
    301.             }
    302.             break;
    303.         case 2://P34
    304.             if(state == KEY_LONGPRESS)
    305.             {
    306.                 //长按进入闹钟配置
    307.                 settingmode = 2;
    308.                 settingpos = 0;
    309.                 settingclock10ms = 0;
    310.             }
    311.             else if(state == KEY_SINGLECLICK)
    312.             {
    313.                 if(settingmode)
    314.                 {
    315.                     test_settingposleft();//左移1位
    316.                 }
    317.             }
    318.             break;
    319.         case 3://P35
    320.             if(state == KEY_SINGLECLICK)
    321.             {
    322.                 settingmode = 0;//退出设置
    323.                 if(settingmode == 1)
    324.                     clock10ms = 0;
    325.             }
    326.             break;
    327.         default:
    328.             break;
    329.         }
    330.     }
    331. }
    332. /******************** 主函数 **************************/
    333. void main(void)
    334. {
    335.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    336.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    337.     CKCON = 0; //提高访问XRAM速度
    338.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    339.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    340.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    341.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    342.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    343.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    344.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    345.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    346.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    347.     //USB调试及复位所需代码-----
    348.     P3M0 &= ~0x03;
    349.     P3M1 |= 0x03;
    350.     IRC48MCR = 0x80;
    351.     while (!(IRC48MCR & 0x01));
    352.     //如果使用USB-CDC需要下面的两行代码
    353.     USBCLK = 0x00;
    354.     USBCON = 0x90;
    355.     //如果使用USB-HID注释掉上面两行代码
    356.     usb_init();
    357.     //-------------------------
    358.     yuyy_timer0init(10000,test_timer0cb); //10ms触发一次回调
    359.     yuyy_keyinit(test_keycb);
    360.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    361.     EA = 1;     //打开总中断
    362.     while(1)
    363.     {
    364.     }
    365. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-20 16:59:24 | 显示全部楼层
    第19集,NTC温度采集
    NTC(Negative Temperature Coe ficient)是指随温度上升电阻呈指数关系减小、具有负温度系数的热敏电阻现象和材料。
    利用这一特性可以通过ADC来测量环境温度,将测量出的adc值通过查表的方式逆推为温度值。
    QQ截图20230519153332.png


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-21 15:06:12 | 显示全部楼层
    第20集,串口通信
    通信指设备之间通过一定的协议进行的信息交换。
    每次发送一位数据的称为串行通信,多位一起传输的称为并行通信。串口通信是串行通信的其中的一种
    串口通信(Serial Communication),是指外设和计算机间,通过数据信号线、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。
    接线方式
    QQ截图20230519153919.png

    课后练习
    QQ截图20230521145433.png

    由于没有数码管和测温模块,所以用usb-hid模拟数码管,用存储的几个数据模拟温度值,用P35上的LED亮灭模拟蜂鸣器开关
    运行效果


    代码
    1. //USB调试及复位所需定义
    2. char *USER_DEVICEDESC = NULL;
    3. char *USER_PRODUCTDESC = NULL;
    4. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    5. const uint8_t ledsegcodes[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
    6. #define FOSC 24000000UL
    7. #define BRT (65536 - (FOSC / 115200+2) / 4)
    8. //加 2 操作是为了让 Keil 编译器
    9. //自动实现四舍五入运算
    10. bit busy;
    11. uint8_t rxbuffer[16];
    12. uint8_t rxcount = 0;
    13. int temps[] = {2650,-1035,40,-10,560,-100};//模拟温度值 26.50 -10.35
    14. uint8_t tempindex = 0;
    15. uint8_t rxfinishflag = 0;
    16. void Uart2Init()
    17. {
    18.     P_SW2 = 0x80; //串口2 rxP10 txP11
    19.     S2CFG = 0x01; //无帧错检测功能,波特率不加倍,固定为 Fosc/12
    20.     S2CON = 0x50; //可变波特率8位数据方式,允许串口接收数据
    21.     T2L = BRT;
    22.     T2H = BRT >> 8;
    23.     T2x12 = 1;
    24.     T2R = 1;
    25.     busy = 0;
    26. }
    27. void Uart2Send(uint8_t dat)
    28. {
    29.     while (busy);
    30.     busy = 1;
    31.     S2BUF = dat;
    32. }
    33. void Uart2SendStr(char *p)
    34. {
    35.     while (*p)
    36.     {
    37.         Uart2Send(*p++);
    38.     }
    39. }
    40. void procrxdata()
    41. {
    42.     int temp;
    43.     char txbuffer[8] = {0};
    44.     uint8_t segdatas[8]={0x00};
    45.     uint8_t segindex = 7;
    46.     switch (rxbuffer[0])
    47.     {
    48.     case 'A'://点亮对应的LED
    49.         if(rxcount == 2 && rxbuffer[1] >= '0' && rxbuffer[1] < '8')
    50.         {
    51.             P2 = ~(1<<(rxbuffer[1] - '0'));
    52.         }
    53.         break;
    54.     case 'B'://数码管显示数字
    55.         if(rxcount > 1 || rxcount < 9)
    56.         {
    57.             while (rxcount > 1)
    58.             {
    59.                 rxcount--;
    60.                 if(rxbuffer[rxcount] >= '0' && rxbuffer[rxcount] <= '9')
    61.                 {
    62.                     segdatas[segindex] = ledsegcodes[rxbuffer[rxcount]-'0'];
    63.                 }
    64.                 segindex--;
    65.             }
    66.             SEG7_ShowCode(segdatas);
    67.         }
    68.         break;
    69.     case 'C'://打开关闭蜂鸣器
    70.         if(rxcount == 2 && (rxbuffer[1] == '0' || rxbuffer[1] == '1'))
    71.         {
    72.             P35 = '1' - rxbuffer[1];
    73.         }
    74.         break;
    75.     case 'D'://发送温度
    76.         if(rxcount == 2)
    77.         {
    78.             temp = temps[tempindex];
    79.             rxcount = 0;
    80.             if(temp < 0)
    81.             {
    82.                 txbuffer[rxcount++] = '-';
    83.                 temp = 0 - temp;
    84.             }
    85.             if(temp > 999)
    86.             {
    87.                 txbuffer[rxcount++] = '0' + (temp / 1000);
    88.                 temp = temp%1000;
    89.             }
    90.             txbuffer[rxcount++] = '0' + (temp / 100);
    91.             temp = temp%100;
    92.             txbuffer[rxcount++] = '.';
    93.             txbuffer[rxcount++] = '0' + (temp / 10);
    94.             temp = temp%10;
    95.             txbuffer[rxcount++] = '0' + temp;
    96.             Uart2SendStr(txbuffer);
    97.             tempindex++;
    98.             if(tempindex > 5)
    99.             {
    100.                 tempindex = 0;
    101.             }
    102.         }
    103.         break;
    104.     case 'Z'://发送"Hello STC"
    105.         if(rxcount == 1)
    106.         {
    107.             Uart2SendStr("Hello STC");
    108.         }
    109.         break;
    110.     default:
    111.         break;
    112.     }
    113.     rxcount = 0;
    114.     yuyy_delay_ms(1);
    115. }
    116. void Uart2Isr() interrupt 8
    117. {
    118.     if (S2TI)
    119.     {
    120.         S2TI = 0;
    121.         busy = 0;
    122.     }
    123.     if (S2RI)
    124.     {
    125.         S2RI = 0;
    126.         rxbuffer[rxcount] = S2BUF;
    127.         if(rxcount > 1 && rxbuffer[rxcount-1]=='\r' && rxbuffer[rxcount]=='\n')
    128.         {
    129.             rxcount-=1;
    130.             rxfinishflag = 1;
    131.             S2REN = 0;//关闭接收
    132.         }
    133.         else
    134.             rxcount++;
    135.         if(rxcount > 15)
    136.             rxcount = 0;
    137.     }
    138. }
    139. /******************** 主函数 **************************/
    140. void main(void)
    141. {
    142.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    143.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    144.     CKCON = 0; //提高访问XRAM速度
    145.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    146.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    147.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    148.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    149.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    150.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    151.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    152.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    153.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    154.     //USB调试及复位所需代码-----
    155.     P3M0 &= ~0x03;
    156.     P3M1 |= 0x03;
    157.     IRC48MCR = 0x80;
    158.     while (!(IRC48MCR & 0x01));
    159.     //如果使用USB-CDC需要下面的两行代码
    160.     // USBCLK = 0x00;
    161.     // USBCON = 0x90;
    162.     //如果使用USB-HID注释掉上面两行代码
    163.     usb_init();
    164.     //-------------------------
    165.    
    166.     Uart2Init();
    167.     IE2 = 0x01;
    168.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    169.     EA = 1;     //打开总中断
    170.     while (P32 != 0);
    171.     Uart2SendStr("STC32G test");
    172.     S2REN = 1;//开启接收
    173.     while(1)
    174.     {
    175.         if(rxfinishflag)
    176.         {
    177.             procrxdata();
    178.             rxfinishflag = 0;
    179.             S2REN = 1;//开启接收
    180.         }
    181.     }
    182. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-22 08:58:58 | 显示全部楼层
    第21集,串口应用
    MCU串口出来的信号都是TTL电平
    TTL电平信号规定,+5V等价于逻辑“1”,0V等价于逻辑“0”(采用二进制来表示数据时)。这样的数据通信及电平规定方式,被称做TTL(晶体管-晶体管逻辑电平)信号系统。这是计算机处理器控制的设备内部各部分之间通信的标准技术。
    232或485的通讯距离更长抗干扰能力更强
    C库函数 int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串。
    课后练习
    QQ截图20230521233509.png

    使用串口1和串口2互相通讯,由于没有那么多按键,使用USB-HID虚拟键盘上的0-9ABC按键,按键按下后串口1向串口2发送数据,串口2如果有数据返回,串口1接收后通过USB-HID打印出来

    运行效果



    代码实现

    1. //USB调试及复位所需定义
    2. char *USER_DEVICEDESC = NULL;
    3. char *USER_PRODUCTDESC = NULL;
    4. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    5. const uint8_t ledsegcodes[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
    6. #define FOSC 24000000UL
    7. #define BRT (65536 - (FOSC / 115200+2) / 4)
    8. //加 2 操作是为了让 Keil 编译器
    9. //自动实现四舍五入运算
    10. bit u1busy;
    11. uint8_t u1rxbuffer[16];
    12. uint8_t u1rxcount = 0;
    13. uint8_t u1rxfinishflag = 0;
    14. bit u2busy;
    15. uint8_t u2rxbuffer[16];
    16. uint8_t u2rxcount = 0;
    17. uint8_t u2rxfinishflag = 0;
    18. int temps[] = {2650,-1035,40,-10,560,-100};//模拟温度值 26.50 -10.35
    19. uint8_t tempindex = 0;
    20. void Uart1Init()
    21. {
    22.     P_SW1 = 0x80; //串口1 rxP16 txP17
    23.     SCON = 0x50;
    24.     T2L = BRT;
    25.     T2H = BRT >> 8;
    26.     S1BRT = 1;
    27.     T2x12 = 1;
    28.     T2R = 1;
    29.     u1busy = 0;
    30. }
    31. void Uart1Send(uint8_t dat)
    32. {
    33.     while (u1busy);
    34.     u1busy = 1;
    35.     SBUF = dat;
    36. }
    37. void Uart1SendStr(char *p)
    38. {
    39.     while (*p)
    40.     {
    41.         Uart1Send(*p++);
    42.     }
    43. }
    44. void Uart2Init()
    45. {
    46.     P_SW2 = 0x80; //串口2 rxP10 txP11
    47.     S2CFG = 0x01; //无帧错检测功能,波特率不加倍,固定为 Fosc/12
    48.     S2CON = 0x50; //可变波特率8位数据方式,允许串口接收数据
    49.     T2L = BRT;
    50.     T2H = BRT >> 8;
    51.     T2x12 = 1;
    52.     T2R = 1;
    53.     u2busy = 0;
    54. }
    55. void Uart2Send(uint8_t dat)
    56. {
    57.     while (u2busy);
    58.     u2busy = 1;
    59.     S2BUF = dat;
    60. }
    61. void Uart2SendStr(char *p)
    62. {
    63.     while (*p)
    64.     {
    65.         Uart2Send(*p++);
    66.     }
    67. }
    68. void procrxdata()
    69. {
    70.     int temp;
    71.     char txbuffer[10] = {0};
    72.     uint8_t segdatas[8]={0x00};
    73.     uint8_t segindex = 7;
    74.     switch (u2rxbuffer[0])
    75.     {
    76.     case 'A'://点亮对应的LED
    77.         if(u2rxcount == 2 && u2rxbuffer[1] >= '0' && u2rxbuffer[1] < '8')
    78.         {
    79.             P2 = ~(1<<(u2rxbuffer[1] - '0'));
    80.         }
    81.         break;
    82.     case 'B'://数码管显示数字
    83.         if(u2rxcount > 1 || u2rxcount < 9)
    84.         {
    85.             while (u2rxcount > 1)
    86.             {
    87.                 u2rxcount--;
    88.                 if(u2rxbuffer[u2rxcount] >= '0' && u2rxbuffer[u2rxcount] <= '9')
    89.                 {
    90.                     segdatas[segindex] = ledsegcodes[u2rxbuffer[u2rxcount]-'0'];
    91.                 }
    92.                 segindex--;
    93.             }
    94.             SEG7_ShowCode(segdatas);
    95.         }
    96.         break;
    97.     case 'C'://打开关闭蜂鸣器
    98.         if(u2rxcount == 2 && (u2rxbuffer[1] == '0' || u2rxbuffer[1] == '1'))
    99.         {
    100.             P35 = '1' - u2rxbuffer[1];
    101.         }
    102.         break;
    103.     case 'D'://发送温度
    104.         if(u2rxcount == 2)
    105.         {
    106.             temp = temps[tempindex];
    107.             u2rxcount = 0;
    108.             if(temp < 0)
    109.             {
    110.                 txbuffer[u2rxcount++] = '-';
    111.                 temp = 0 - temp;
    112.             }
    113.             if(temp > 999)
    114.             {
    115.                 txbuffer[u2rxcount++] = '0' + (temp / 1000);
    116.                 temp = temp%1000;
    117.             }
    118.             txbuffer[u2rxcount++] = '0' + (temp / 100);
    119.             temp = temp%100;
    120.             txbuffer[u2rxcount++] = '.';
    121.             txbuffer[u2rxcount++] = '0' + (temp / 10);
    122.             temp = temp%10;
    123.             txbuffer[u2rxcount++] = '0' + temp;
    124.             txbuffer[u2rxcount++] = '\r';
    125.             txbuffer[u2rxcount++] = '\n';
    126.             Uart2SendStr(txbuffer);
    127.             tempindex++;
    128.             if(tempindex > 5)
    129.             {
    130.                 tempindex = 0;
    131.             }
    132.         }
    133.         break;
    134.     case 'Z'://发送"Hello STC"
    135.         if(u2rxcount == 1)
    136.         {
    137.             Uart2SendStr("Hello STC\r\n");
    138.         }
    139.         break;
    140.     default:
    141.         break;
    142.     }
    143.     u2rxcount = 0;
    144.     yuyy_delay_ms(1);
    145. }
    146. void Uart1Isr() interrupt 4
    147. {
    148.     if (TI)
    149.     {
    150.         TI = 0;
    151.         u1busy = 0;
    152.     }
    153.     if (RI)
    154.     {
    155.         RI = 0;
    156.         u1rxbuffer[u1rxcount] = SBUF;
    157.         if(u1rxbuffer[u1rxcount-1]=='\r' && u1rxbuffer[u1rxcount]=='\n')
    158.         {
    159.             u1rxfinishflag = 1;
    160.             REN = 0;//关闭接收
    161.         }
    162.         else
    163.             u1rxcount++;
    164.         if(u1rxcount > 15)
    165.             u1rxcount = 0;
    166.     }
    167. }
    168. void Uart2Isr() interrupt 8
    169. {
    170.     if (S2TI)
    171.     {
    172.         S2TI = 0;
    173.         u2busy = 0;
    174.     }
    175.     if (S2RI)
    176.     {
    177.         S2RI = 0;
    178.         u2rxbuffer[u2rxcount] = S2BUF;
    179.         if(u2rxcount > 1 && u2rxbuffer[u2rxcount-1]=='\r' && u2rxbuffer[u2rxcount]=='\n')
    180.         {
    181.             u2rxcount-=1;
    182.             u2rxfinishflag = 1;
    183.             S2REN = 0;//关闭接收
    184.         }
    185.         else
    186.             u2rxcount++;
    187.         if(u2rxcount > 15)
    188.             u2rxcount = 0;
    189.     }
    190. }
    191. /******************** 主函数 **************************/
    192. void main(void)
    193. {
    194.     char u1txdats[] = {'A','0','\r','\n'};
    195.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    196.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    197.     CKCON = 0; //提高访问XRAM速度
    198.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    199.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    200.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    201.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    202.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    203.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    204.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    205.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    206.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    207.     //USB调试及复位所需代码-----
    208.     P3M0 &= ~0x03;
    209.     P3M1 |= 0x03;
    210.     IRC48MCR = 0x80;
    211.     while (!(IRC48MCR & 0x01));
    212.     //如果使用USB-CDC需要下面的两行代码
    213.     // USBCLK = 0x00;
    214.     // USBCON = 0x90;
    215.     //如果使用USB-HID注释掉上面两行代码
    216.     usb_init();
    217.     //-------------------------
    218.    
    219.     Uart1Init();
    220.     Uart2Init();
    221.     ES = 1;
    222.     ES2 = 1;
    223.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    224.     EA = 1;     //打开总中断
    225.     REN = 1;
    226.     S2REN = 1;//开启接收
    227.     while(1)
    228.     {
    229.         if (DeviceState != DEVSTATE_CONFIGURED)        //判断USB设备识别是否完成
    230.             continue;
    231.         if (bUsbOutReady)
    232.         {
    233.             if ((UsbOutBuffer[0] == 'K') &&
    234.                 (UsbOutBuffer[1] == 'E') &&
    235.                 (UsbOutBuffer[2] == 'Y') &&
    236.                 (UsbOutBuffer[3] == 'P'))
    237.             {
    238.                 switch (UsbOutBuffer[5])
    239.                 {
    240.                     case 0x30:
    241.                     case 0x31:
    242.                     case 0x32:
    243.                     case 0x33:
    244.                     case 0x34:
    245.                     case 0x35:
    246.                     case 0x36:
    247.                     case 0x37: //按键0-7
    248.                         u1txdats[1] = '0' + (UsbOutBuffer[5]-0x30);
    249.                         Uart1SendStr(u1txdats);
    250.                         break;
    251.                     case 0x38: //按键8
    252.                         Uart1SendStr("B0000\r\n");
    253.                         break;
    254.                     case 0x39: //按键9
    255.                         Uart1SendStr("Z\r\n");
    256.                         break;
    257.                     case 0x41: //按键A
    258.                         Uart1SendStr("C0\r\n");
    259.                         break;
    260.                     case 0x42: //按键B
    261.                         Uart1SendStr("C1\r\n");
    262.                         break;
    263.                     case 0x43: //按键C
    264.                         Uart1SendStr("D0\r\n");
    265.                         break;
    266.                     default:
    267.                         break;
    268.                 }
    269.                 usb_OUT_done();
    270.             }
    271.         }
    272.         if(u1rxfinishflag)
    273.         {
    274.             //接收到的数据通过usb-hid打印
    275.             printf(u1rxbuffer);
    276.             u1rxfinishflag = 0;
    277.             u1rxcount = 0;
    278.             memset(u1rxbuffer,0);
    279.             REN = 1;//开启接收
    280.         }
    281.         if(u2rxfinishflag)
    282.         {
    283.             procrxdata();
    284.             u2rxfinishflag = 0;
    285.             S2REN = 1;//开启接收
    286.         }
    287.     }
    288. }
    复制代码



    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 22:23
  • 签到天数: 132 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1157

    积分

    金牌会员

    积分
    1157
     楼主| 发表于 2023-5-22 19:03:26 | 显示全部楼层
    第22集,CDC串口通信
    无需USB转TTL,一根数据线就能通讯,P30和P31连接USB的D-和D+加上单片机外围即可实现下载与通讯
    CDC串口的优点
    QQ截图20230522090415.png

    CDC不停电下载回顾,本帖6楼https://www.stcaimcu.com/forum.p ... =2110&pid=13843
    CDC串口通信练习
    QQ截图20230522093612.png

    运行效果


    代码实现
    1. //USB调试及复位所需定义
    2. char *USER_DEVICEDESC = NULL;
    3. char *USER_PRODUCTDESC = NULL;
    4. char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
    5. const uint8_t ledsegcodes[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
    6. int temps[] = {2650,-1035,40,-10,560,-100};//模拟温度值 26.50 -10.35
    7. uint8_t tempindex = 0;
    8. /******************** 主函数 **************************/
    9. void main(void)
    10. {
    11.     int temp;
    12.     char txbuffer[10] = {0};
    13.     uint8_t segdatas[8]={0x00};
    14.     uint8_t segindex = 7;
    15.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    16.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    17.     CKCON = 0; //提高访问XRAM速度
    18.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    19.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    20.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    21.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    22.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    23.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    24.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    25.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    26.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    27.     //USB调试及复位所需代码-----
    28.     P3M0 &= ~0x03;
    29.     P3M1 |= 0x03;
    30.     IRC48MCR = 0x80;
    31.     while (!(IRC48MCR & 0x01));
    32.     //如果使用USB-CDC需要下面的两行代码
    33.     USBCLK = 0x00;
    34.     USBCON = 0x90;
    35.     //如果使用USB-HID注释掉上面两行代码
    36.     usb_init();
    37.     //-------------------------
    38.    
    39.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    40.     EA = 1;     //打开总中断
    41.     while(1)
    42.     {
    43.         if (DeviceState != DEVSTATE_CONFIGURED)        //判断USB设备识别是否完成
    44.             continue;
    45.         if (bUsbOutReady)
    46.         {
    47.             // printf("rec len %d \r\n",OutNumber);
    48.             // USB_SendData(UsbOutBuffer,OutNumber);
    49.             switch (UsbOutBuffer[0])
    50.             {
    51.                 case 'A'://点亮对应的LED
    52.                     if(OutNumber == 2 && UsbOutBuffer[1] >= '0' && UsbOutBuffer[1] < '8')
    53.                     {
    54.                         P2 = ~(1<<(UsbOutBuffer[1] - '0'));
    55.                     }
    56.                     break;
    57.                 case 'B'://数码管显示数字
    58.                     if(OutNumber > 1 || OutNumber < 9)
    59.                     {
    60.                         segindex = 7;
    61.                         while (OutNumber > 1)
    62.                         {
    63.                             OutNumber--;
    64.                             if(UsbOutBuffer[OutNumber] >= '0' && UsbOutBuffer[OutNumber] <= '9')
    65.                             {
    66.                                 segdatas[segindex] = ledsegcodes[UsbOutBuffer[OutNumber]-'0'];
    67.                             }
    68.                             segindex--;
    69.                         }
    70.                         SEG7_ShowCode(segdatas);
    71.                     }
    72.                     break;
    73.                 case 'C'://打开关闭蜂鸣器
    74.                     if(OutNumber == 2 && (UsbOutBuffer[1] == '0' || UsbOutBuffer[1] == '1'))
    75.                     {
    76.                         P35 = '1' - UsbOutBuffer[1];
    77.                     }
    78.                     break;
    79.                 case 'D'://发送温度
    80.                     if(OutNumber == 2)
    81.                     {
    82.                         temp = temps[tempindex];
    83.                         OutNumber = 0;
    84.                         if(temp < 0)
    85.                         {
    86.                             txbuffer[OutNumber++] = '-';
    87.                             temp = 0 - temp;
    88.                         }
    89.                         if(temp > 999)
    90.                         {
    91.                             txbuffer[OutNumber++] = '0' + (temp / 1000);
    92.                             temp = temp%1000;
    93.                         }
    94.                         txbuffer[OutNumber++] = '0' + (temp / 100);
    95.                         temp = temp%100;
    96.                         txbuffer[OutNumber++] = '.';
    97.                         txbuffer[OutNumber++] = '0' + (temp / 10);
    98.                         temp = temp%10;
    99.                         txbuffer[OutNumber++] = '0' + temp;
    100.                         USB_SendData(txbuffer,OutNumber);
    101.                         tempindex++;
    102.                         if(tempindex > 5)
    103.                         {
    104.                             tempindex = 0;
    105.                         }
    106.                     }
    107.                     break;
    108.                 case 'Z'://发送"Hello STC"
    109.                     if(OutNumber == 1)
    110.                     {
    111.                         USB_SendData("Hello STC",9);
    112.                     }
    113.                     break;
    114.                 default:
    115.                     break;
    116.             }
    117.             usb_OUT_done();
    118.         }
    119.     }
    120. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-11 18:59 , Processed in 0.121638 second(s), 73 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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