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

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

[复制链接]
  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-5-23 08:52:07 | 显示全部楼层
    本帖最后由 yuyy1989 于 2023-5-23 11:28 编辑

    第23集,看门狗
    系统复位,复位的主要作用是把单片机内部的特殊功能寄存器置于初始状态,使单片机硬件、软件从一个确定的、唯一的起点开始工作。
    复位方式包括
    QQ截图20230523081245.png
    看门狗,看门狗是一个计数器,它的基本功能是在软件问题和程序跑偏后重启系统。看门狗正常工作时会自动计数,程序进程会定时将其归零。如果系统在某个地方卡住了或者跑了,定时器就会溢出,是系统强制复位。
    软件的可靠性一直是一个关键问题。任何使用软件的人都可能遇到电脑死机或程序失控的问题,这种问题在嵌入式系统中也存在。由于单片机抗干扰能力有限,在工业现场仪器仪表中,经常因电压不稳和电弧干扰而死机。在水表、电表无人值守的情况下,系统因干扰无法重启。为了保证系统在受到干扰后能自动恢复正常,看门狗定时器的使用是非常有价值的。
    看门狗实现原理,在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去清理看门狗(也叫喂狗),那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位。所以,在使用有看门狗的芯片时要注意清理看门狗。
    看门狗实验,初始状态P2上的LED全亮,按下P34后开启看门狗,P2上的LED流水灯,按住P35按键1秒后看门狗复位P2上的LED全亮


    代码实现

    1. #define MAIN_Fosc       24000000L   //定义主时钟
    2. void delay_ms(uint16_t ms)
    3. {
    4.     uint16_t i;
    5.     do{
    6.         i = MAIN_Fosc / 6000;
    7.         while(--i);   //6T per loop
    8.     }while(--ms);
    9. }
    10. /******************** 主函数 **************************/
    11. void main(void)
    12. {
    13.     uint8_t ledindex = 0;
    14.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    15.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    16.     CKCON = 0; //提高访问XRAM速度
    17.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    18.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    19.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    20.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    21.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    22.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    23.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    24.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    25.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    26.     //USB调试及复位所需代码-----
    27.     P3M0 &= ~0x03;
    28.     P3M1 |= 0x03;
    29.     IRC48MCR = 0x80;
    30.     while (!(IRC48MCR & 0x01));
    31.     //如果使用USB-CDC需要下面的两行代码
    32.     // USBCLK = 0x00;
    33.     // USBCON = 0x90;
    34.     //如果使用USB-HID注释掉上面两行代码
    35.     usb_init();
    36.     //-------------------------
    37.    
    38.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    39.     EA = 1;     //打开总中断
    40.     P2 = 0x00; //复位后P2上的LED全部亮起
    41.     while (P34 != 0);
    42.     WDT_CONTR = 0x25; //24M主频下约1.05秒
    43.     while(1)
    44.     {
    45.         if(P35 != 0) //如果P35按键没有按下
    46.         {
    47.             CLR_WDT = 1; //清零看门狗
    48.         }
    49.         delay_ms(100);
    50.         P2 = ~(1<<ledindex);
    51.         ledindex++;
    52.         if(ledindex > 7)
    53.             ledindex = 0;
    54.     }
    55. }
    复制代码



    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-5-23 16:07:15 | 显示全部楼层
    第24集,比较器


    核心作用就是通过比较两个电压的大小,来及时的响应某些动作
    QQ截图20230523112926.png
    QQ截图20230523112942.png

    手册里例程的上升沿下降沿的注释标反了
    QQ截图20230523155307.png QQ截图20230523155514.png

    上升沿时0变1,触发中断后CMPRES为1,下降沿是1变0,触发中断后CMPRES为0

    代码示例

    1. #include "stc32g.h"
    2. #include "intrins.h"
    3. void main(void)
    4. {
    5.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    6.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    7.     CKCON = 0; //提高访问XRAM速度
    8.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    9.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    10.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    11.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    12.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    13.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    14.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    15.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    16.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    17.     //USB调试及复位所需代码-----
    18.     P3M0 &= ~0x03;
    19.     P3M1 |= 0x03;
    20.     IRC48MCR = 0x80;
    21.     while (!(IRC48MCR & 0x01));
    22.     //如果使用USB-CDC需要下面的两行代码
    23.     // USBCLK = 0x00;
    24.     // USBCON = 0x90;
    25.     //如果使用USB-HID注释掉上面两行代码
    26.     usb_init();
    27.     //-------------------------
    28.     CMPEXCFG |= 0x40; //比较器 DC 迟滞10mv P3.6负极 P3.7正极
    29.     CMPCR1 = 0xB0; //开启比较功能,使能上升沿和下降沿中断
    30.     CMPCR2= 0x00; //使能0.1us模拟滤波
    31.    
    32.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    33.     EA = 1;     //打开总中断
    34.     while(1)
    35.     {
    36.     }
    37. }
    38. void CMP_Isr() interrupt 21
    39. {
    40.     CMPIF = 0; //清中断标志
    41.     if (CMPRES)
    42.     {
    43.         P20 = !P20; //上升沿(0变1)中断测试端口
    44.     }
    45.     else
    46.     {
    47.         P21 = !P21; //下降沿(1变0)中断测试端口
    48.     }
    49. }
    复制代码



    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 10:23
  • 签到天数: 148 天

    [LV.7]常住居民III

    4

    主题

    70

    回帖

    1121

    积分

    金牌会员

    积分
    1121
    发表于 2023-5-24 10:37:12 | 显示全部楼层
    回复 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-12-13 11:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    337

    回帖

    1649

    积分

    版主

    积分
    1649
    发表于 2023-5-24 11:50:18 | 显示全部楼层
    【免费+包邮】 送/申样热线:0513-55012928、0513-55012929、0513-55012966
    工作时间:  8:30-12:00  13:00-17:30(周一 到 周五, 法定节假日除外),也可加如下 QQ 或 微信 申请
    加STC华南区客服刘经理QQ: 3398500488 ;微信:18106296592  要求 【免费+包邮】 送, 还免费教你仿真  
    加STC华南区客服曹经理QQ:1933892258 ;微信:18106296595 要求 【免费+包邮】 送, 还免费教你仿真
    加STC华东区客服聂经理QQ:2593903262;微信:18106296598  要求 【免费+包邮】 送, 还免费教你仿真
    加STC西北区客服孙经理QQ: 1347154513 ;微信:18106296593  要求 【免费+包邮】 送, 还免费教你仿真
    加STC华北区客服石经理QQ: 1638975601 ;微信:19952583876  要求 【免费+包邮】 送, 还免费教你仿真
    加STC华中区客服唐经理QQ:2571301708 ;微信:18106296589 要求 【免费+包邮】 送, 还免费教你仿真
    加STC东北区客服张经理QQ:3141888640 ;微信:19952583265   要求 【免费+包邮】 送, 还免费教你仿真
    加STC西南区客服张经理QQ:3141888640 ;微信:19952583265   要求 【免费+包邮】 送, 还免费教你仿真

    或者加我QQ:2269694595,我帮您联系对应业务员
    QQ:2269694595     微信:18106296594
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-5-26 15:12:07 | 显示全部楼层
    第25集,FLASH模拟EEPROM

    实验箱还没到,先继续看

    FLASH和EEPROM是什么
    EEPROM的全称是“电可擦除可编程只读存储器” ,即 Electrically Erasable Programmable Read-Only Memory:是相对于紫外擦除的rom来讲的。但是今天已经存在多种 EEPROM 的变种,变成了一类存储器的统称。
    狭义的EEPROM:
    这种rom的特点是可以随机访问和修改任何一个字节。这是最传统的一种EEPROM,掉电后数据不丢失,可以保存 100年,可以擦写100w次。具有较高的可靠性,但是电路复杂/成本也高。因此目前的 EEPROM 都是几十千字节到几百千字节的,绝少有超过 512K 的。
    Flash:
    Flash属于广义的EEPROM,因为它也是电擦除的ROM。但是为了区别于一般的按字节为单位的擦写的EEPROM,我们都叫它Flash。FLASH如果数据不为OXFF,需要擦除之后才能写入

    实验:点击P32切换LED亮起,点击P35保存LED状态,重新通电恢复保存的LED状态

    运行效果


    代码实现
    1. #include "stc32g.h"
    2. #include "intrins.h"
    3. #define MAIN_Fosc       24000000L   //定义主时钟
    4. void delay_ms(uint16_t ms)
    5. {
    6.     uint16_t i;
    7.     do{
    8.         i = MAIN_Fosc / 6000;
    9.         while(--i);   //6T per loop
    10.     }while(--ms);
    11. }
    12. void IapIdle(void)
    13. {
    14.     IAP_CONTR = 0; //关闭 IAP 功能
    15.     IAP_CMD = 0; //清除命令寄存器
    16.     IAP_TRIG = 0; //清除触发寄存器
    17.     IAP_ADDRE = 0x00;
    18.     IAP_ADDRH = 0x00;
    19.     IAP_ADDRL = 0x00;
    20. }
    21. uint8_t IapRead(uint32_t addr)
    22. {
    23.     char dat;
    24.     IAP_CONTR = 0x80; //使能 IAP
    25.     IAP_TPS = 12; //设置等待参数 12MHz
    26.     IAP_CMD = 1; //设置 IAP 读命令
    27.     IAP_ADDRL = addr; //设置 IAP 低地址
    28.     IAP_ADDRH = addr >> 8; //设置 IAP 高地址
    29.     IAP_ADDRE = addr >> 16; //设置 IAP 最高地址
    30.     IAP_TRIG = 0x5a; //写触发命令(0x5a)
    31.     IAP_TRIG = 0xa5; //写触发命令(0xa5)
    32.     _nop_();
    33.     _nop_();
    34.     _nop_();
    35.     _nop_();
    36.     dat = IAP_DATA; //读 IAP 数据
    37.     IapIdle(); //关闭 IAP 功能
    38.     return dat;
    39. }
    40. void IapProgram(uint32_t addr, uint8_t dat)
    41. {
    42.     IAP_CONTR = 0x80; //使能 IAP
    43.     IAP_TPS = 12; //设置等待参数 12MHz
    44.     IAP_CMD = 2; //设置 IAP 写命令
    45.     IAP_ADDRL = addr; //设置 IAP 低地址
    46.     IAP_ADDRH = addr >> 8; //设置 IAP 高地址
    47.     IAP_ADDRE = addr >> 16; //设置 IAP 最高地址
    48.     IAP_DATA = dat; //写 IAP 数据
    49.     IAP_TRIG = 0x5a; //写触发命令(0x5a)
    50.     IAP_TRIG = 0xa5; //写触发命令(0xa5)
    51.     _nop_();
    52.     _nop_();
    53.     _nop_();
    54.     _nop_();
    55.     IapIdle(); //关闭 IAP 功能
    56. }
    57. void IapErase(uint32_t addr)
    58. {
    59.     IAP_CONTR = 0x80; //使能 IAP
    60.     IAP_TPS = 12; //设置等待参数 12MHz
    61.     IAP_CMD = 3; //设置 IAP 擦除命令
    62.     IAP_ADDRL = addr; //设置 IAP 低地址
    63.     IAP_ADDRH = addr >> 8; //设置 IAP 高地址
    64.     IAP_ADDRE = addr >> 16; //设置 IAP 最高地址
    65.     IAP_TRIG = 0x5a; //写触发命令(0x5a)
    66.     IAP_TRIG = 0xa5; //写触发命令(0xa5)
    67.     _nop_();
    68.     _nop_();
    69.     _nop_();
    70.     _nop_(); //
    71.     IapIdle(); //关闭 IAP 功能
    72. }
    73. void main(void)
    74. {
    75.     uint8_t ledindex = 0;
    76.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    77.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    78.     CKCON = 0; //提高访问XRAM速度
    79.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    80.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    81.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    82.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    83.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    84.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    85.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    86.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    87.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    88.     //USB调试及复位所需代码-----
    89.     P3M0 &= ~0x03;
    90.     P3M1 |= 0x03;
    91.     IRC48MCR = 0x80;
    92.     while (!(IRC48MCR & 0x01));
    93.     //如果使用USB-CDC需要下面的两行代码
    94.     // USBCLK = 0x00;
    95.     // USBCON = 0x90;
    96.     //如果使用USB-HID注释掉上面两行代码
    97.     usb_init();
    98.     //-------------------------
    99.     ledindex = IapRead(0x0000);
    100.     if(ledindex > 7)
    101.         ledindex = 0;
    102.     P2 = ~(1<<ledindex);
    103.    
    104.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    105.     EA = 1;     //打开总中断
    106.     while(1)
    107.     {
    108.         if(P32 == 0)
    109.         {
    110.             delay_ms(30);
    111.             if(P32 == 0)
    112.             {
    113.                 while(P32 == 0);
    114.                     ledindex += 1;
    115.                 if(ledindex > 7)
    116.                 ledindex = 0;
    117.                 P2 = ~(1<<ledindex);
    118.             }
    119.         }
    120.         if(P35 == 0)
    121.         {
    122.             delay_ms(30);
    123.             if(P35 == 0)
    124.             {
    125.                 while(P35 == 0);
    126.                 IapErase(0x0000);
    127.                 IapProgram(0x0000,ledindex);
    128.             }
    129.         }
    130.     }
    131. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-5-27 21:54:54 | 显示全部楼层
    用实验箱验证了一下之前写的数码管驱动程序,看来可以正常运行

    微信图片_20230527215210.jpg



    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-5-29 21:04:45 | 显示全部楼层
    验证了一下之前普通按键、矩阵按键、ADC按键都放到一个文件里的程序,功能正常

    数码管第1位数是按键类型0普通按键 1矩阵按键 2ADC按键,第2位是按键编号,第3位是按键动作1按键按下 2松开


    点评

    楼主学习精神值得称赞,希望能配合STC32G12K128实验箱9.6版,分享更多学习经验哦  详情 回复 发表于 2023-5-30 09:17
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-12-13 11:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    337

    回帖

    1649

    积分

    版主

    积分
    1649
    发表于 2023-5-30 09:17:25 | 显示全部楼层
    yuyy1989 发表于 2023-5-29 21:04
    验证了一下之前普通按键、矩阵按键、ADC按键都放到一个文件里的程序,功能正常

    数码管第1位数是按键类型0 ...

    楼主学习精神值得称赞,希望能配合STC32G12K128实验箱9.6版,分享更多学习经验哦
    QQ:2269694595     微信:18106296594
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-5-30 21:33:42 | 显示全部楼层
    第26集,DS18B20温度传感器
    DS18B20是常用的数字温度传感器,其输出的是数字信号,仅需要一根数据线就能通讯
    微信图片_20230530212156.jpg

    演示代码
    1. #define DP P33
    2. uint8_t yuyy_ds18b20_reset(void)
    3. {
    4.     uint8_t flag;
    5.     DP = 0;
    6.     yuyy_delay_us(480);
    7.     DP = 1;
    8.     yuyy_delay_us(60);
    9.     flag = DP;
    10.     yuyy_delay_us(420);
    11.     return flag;
    12. }
    13. void yuyy_ds18b20_write0(void)
    14. {
    15.     DP = 0;
    16.     yuyy_delay_us(60);
    17.     DP = 1;
    18.     yuyy_delay_us(2);
    19. }
    20. void yuyy_ds18b20_write1(void)
    21. {
    22.     DP = 0;
    23.     yuyy_delay_us(2);
    24.     DP = 1;
    25.     yuyy_delay_us(60);
    26. }
    27. void yuyy_ds18b20_writebyte(uint8_t dat)
    28. {
    29.     uint8_t i = 0;
    30.     while (i<8)
    31.     {
    32.         if(dat & 0x01)
    33.             yuyy_ds18b20_write1();
    34.         else
    35.             yuyy_ds18b20_write0();
    36.         dat >>= 1;
    37.         i++;
    38.     }
    39.    
    40. }
    41. uint8_t yuyy_ds18b20_readbyte(void)
    42. {
    43.     uint8_t i = 0,dat = 0;
    44.     while (i<8)
    45.     {
    46.         dat >>= 1;
    47.         DP = 0;
    48.         yuyy_delay_us(2);
    49.         DP = 1;
    50.         yuyy_delay_us(2);
    51.         if(DP)
    52.             dat |= 0x80;
    53.         else
    54.             dat &= 0x7F;
    55.         yuyy_delay_us(60);
    56.         i++;
    57.     }
    58.     return dat;
    59. }
    60. float yuyy_ds18b20_readtemp(void)
    61. {
    62.     float temp = -999;
    63.     uint8_t err = 0,th,tl,retry = 0;
    64.     err = yuyy_ds18b20_reset();           //复位
    65.     while (err && retry < 5)
    66.     {
    67.         err = yuyy_ds18b20_reset();
    68.         retry++;
    69.     }
    70.    
    71.     if(err == 0)
    72.     {
    73.         yuyy_ds18b20_writebyte(0xCC);   //跳过ROM指令
    74.         yuyy_ds18b20_writebyte(0x44);   //开始转化
    75.         while (DP == 0);
    76.         yuyy_ds18b20_reset();           //复位
    77.         yuyy_ds18b20_writebyte(0xCC);   //跳过ROM指令
    78.         yuyy_ds18b20_writebyte(0xBE);   //读取
    79.         tl = yuyy_ds18b20_readbyte();
    80.         th = yuyy_ds18b20_readbyte();
    81.         temp = ((int16_t)((th<<8) | tl)) * 0.0625;
    82.     }
    83.     return temp;
    84. }
    85. void test_showsegled(void)
    86. {
    87.     yuyy_segled_show();
    88. }
    89. /******************** 主函数 **************************/
    90. void main(void)
    91. {
    92.     uint16_t num1 = 200;
    93.     float temp = 0;
    94.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    95.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    96.     CKCON = 0; //提高访问XRAM速度
    97.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    98.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    99.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    100.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    101.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    102.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    103.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    104.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    105.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    106.     //USB调试及复位所需代码-----
    107.     P3M0 &= ~0x03;
    108.     P3M1 |= 0x03;
    109.     IRC48MCR = 0x80;
    110.     while (!(IRC48MCR & 0x01));
    111.     //如果使用USB-CDC需要下面的两行代码
    112.     // USBCLK = 0x00;
    113.     // USBCON = 0x90;
    114.     //如果使用USB-HID注释掉上面两行代码
    115.     usb_init();
    116.     //-------------------------
    117.     yuyy_timer0init(1000,test_showsegled);
    118.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    119.     EA = 1;     //打开总中断
    120.    
    121.     while(1)
    122.     {
    123.         delay_ms(1);
    124.         if(num1 < 200)
    125.         {
    126.             num1++;
    127.         }
    128.         else
    129.         {
    130.             num1 = 0;
    131.             temp = yuyy_ds18b20_readtemp();
    132.             yuyy_segled_shwowfloatnums(temp,0xFF,2,0);
    133.         }
    134.     }
    135. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    昨天 23:16
  • 签到天数: 133 天

    [LV.7]常住居民III

    3

    主题

    65

    回帖

    1161

    积分

    金牌会员

    积分
    1161
     楼主| 发表于 2023-6-1 21:48:24 | 显示全部楼层
    第27集,软件模拟SPI
    SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线。
    一般使用4条线:串行时钟线(SCLK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线NSS。
    模拟SPI读取flash的id
    实验箱原理图上标的flash是pm25lv040
    QQ截图20230601210216.png

    但我这个实际上是gd25q40ctig,查看这个flash的spi协议,数据在第一个时钟边沿采样,第二个边沿修改
    QQ截图20230601210149.png

    读取ID的命令,和对应的ID
    QQ图片20230601214547.png

    QQ截图20230601214126.png

    程序读取结果
    QQ截图20230601211136.png

    代码实现
    1. typedef enum
    2. {
    3.     YUYY_SOFT_SPI_MSB = 0,
    4.     YUYY_SOFT_SPI_LSB
    5. } Yuyy_Soft_Spi_Data_Type;
    6. typedef enum
    7. {
    8.     YUYY_SOFT_SPI_C1S2 = 0, //第一个边沿修改数据,第2个边沿采样
    9.     YUYY_SOFT_SPI_C2S1
    10. } Yuyy_Soft_Spi_Data_Sample_Type;
    11. typedef enum
    12. {
    13.     YUYY_SOFT_SPI_SCK_IDLE_LOW = 0,
    14.     YUYY_SOFT_SPI_SCK_IDLE_HIGH
    15. } Yuyy_Soft_Spi_Sck_Idle_Type;
    16. #define SOFT_SPI_CS P22
    17. #define SOFT_SPI_SCK P25
    18. #define SOFT_SPI_MOSI P23
    19. #define SOFT_SPI_MISO P24
    20. Yuyy_Soft_Spi_Data_Type spi_dt;
    21. Yuyy_Soft_Spi_Data_Sample_Type spi_cpha;
    22. Yuyy_Soft_Spi_Sck_Idle_Type spi_cpol;
    23. void yuyy_soft_spi_delay()
    24. {
    25.     uint8_t i = 3;
    26.     while(i--);
    27. }
    28. void yuyy_soft_spi_init(Yuyy_Soft_Spi_Data_Type dt,Yuyy_Soft_Spi_Data_Sample_Type cpha,Yuyy_Soft_Spi_Sck_Idle_Type cpol)
    29. {
    30.     SOFT_SPI_CS = 1;
    31.     spi_dt = dt;
    32.     spi_cpha = cpha;
    33.     spi_cpol = cpol;
    34.     if(spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH)
    35.         SOFT_SPI_SCK = 1;
    36.     else
    37.         SOFT_SPI_SCK = 0;
    38.     SOFT_SPI_MISO = 1;
    39.     SOFT_SPI_MOSI = 1;
    40. }
    41. void yuyy_soft_spi_cs(uint8_t lev)
    42. {
    43.     SOFT_SPI_CS = lev;
    44.     yuyy_soft_spi_delay();
    45. }
    46. void yuyy_soft_spi_write_byte(uint8_t dat)
    47. {
    48.     uint8_t i = 0;
    49.     while(i<8)
    50.     {
    51.         if(spi_cpha == YUYY_SOFT_SPI_C1S2)
    52.         {
    53.             SOFT_SPI_SCK = (spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH ? 0 : 1);
    54.         }
    55.         if(spi_dt == YUYY_SOFT_SPI_MSB)
    56.         {
    57.             if(dat & 0x80)
    58.                 SOFT_SPI_MOSI = 1;
    59.             else
    60.                 SOFT_SPI_MOSI = 0;
    61.             dat <<= 1;
    62.         }
    63.         else
    64.         {
    65.             if(dat & 0x01)
    66.                 SOFT_SPI_MOSI = 1;
    67.             else
    68.                 SOFT_SPI_MOSI = 0;
    69.             dat >>= 1;
    70.         }
    71.         if(spi_cpha == YUYY_SOFT_SPI_C2S1)
    72.         {
    73.             SOFT_SPI_SCK = (spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH ? 0 : 1);
    74.         }
    75.         yuyy_soft_spi_delay();
    76.         SOFT_SPI_SCK = (spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH ? 1 : 0);
    77.         i++;
    78.     }
    79. }
    80. uint8_t yuyy_soft_spi_read_byte()
    81. {
    82.     uint8_t i = 0,dat = 0;
    83.     while(i<8)
    84.     {
    85.         if(spi_cpha == YUYY_SOFT_SPI_C2S1)
    86.         {
    87.             SOFT_SPI_SCK = (spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH ? 0 : 1);
    88.         }
    89.         if(spi_dt == YUYY_SOFT_SPI_MSB)
    90.         {
    91.             dat <<= 1;
    92.             if(SOFT_SPI_MISO)
    93.                 dat |= 0x01;
    94.             else
    95.                 dat &= 0xFE;
    96.         }
    97.         else
    98.         {
    99.             dat >>= 1;
    100.             if(SOFT_SPI_MISO)
    101.                 dat |= 0x80;
    102.             else
    103.                 dat &= 0x7F;
    104.         }
    105.         if(spi_cpha == YUYY_SOFT_SPI_C1S2)
    106.         {
    107.             SOFT_SPI_SCK = (spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH ? 0 : 1);
    108.         }
    109.         yuyy_soft_spi_delay();
    110.         SOFT_SPI_SCK = (spi_cpol == YUYY_SOFT_SPI_SCK_IDLE_HIGH ? 1 : 0);
    111.         i++;
    112.     }
    113.     return dat;
    114. }
    115. void main(void)
    116. {
    117.     uint8_t id1,id2,id3;
    118.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    119.     EAXFR = 1; //扩展寄存器(XFR)访问使能
    120.     CKCON = 0; //提高访问XRAM速度
    121.     RSTFLAG |= 0x04;   //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
    122.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    123.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    124.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    125.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    126.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    127.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    128.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    129.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    130.     //USB调试及复位所需代码-----
    131.     P3M0 &= ~0x03;
    132.     P3M1 |= 0x03;
    133.     IRC48MCR = 0x80;
    134.     while (!(IRC48MCR & 0x01));
    135.     //如果使用USB-CDC需要下面的两行代码
    136.     // USBCLK = 0x00;
    137.     // USBCON = 0x90;
    138.     //如果使用USB-HID注释掉上面两行代码
    139.     usb_init();
    140.     //-------------------------
    141.     yuyy_soft_spi_init(YUYY_SOFT_SPI_MSB,YUYY_SOFT_SPI_C2S1,YUYY_SOFT_SPI_SCK_IDLE_HIGH);
    142.     EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    143.     EA = 1;     //打开总中断
    144.     while (P32 != 0);
    145.     yuyy_soft_spi_cs(0);
    146.     yuyy_soft_spi_write_byte(0xAB);
    147.     yuyy_soft_spi_write_byte(0x00);
    148.     yuyy_soft_spi_write_byte(0x00);
    149.     yuyy_soft_spi_write_byte(0x00);
    150.     id1 = yuyy_soft_spi_read_byte();
    151.     yuyy_soft_spi_cs(1);
    152.     printf_hid("发送命令0xAB 读取到ID:0x%02X\r\n",id1);
    153.     delay_ms(100);
    154.     yuyy_soft_spi_cs(0);
    155.     yuyy_soft_spi_write_byte(0x90);
    156.     yuyy_soft_spi_write_byte(0x00);
    157.     yuyy_soft_spi_write_byte(0x00);
    158.     yuyy_soft_spi_write_byte(0x00);
    159.     id1 = yuyy_soft_spi_read_byte();
    160.     id2 = yuyy_soft_spi_read_byte();
    161.     yuyy_soft_spi_cs(1);
    162.     printf_hid("发送命令0x90 读取到ID:0x%02X 0x%02X\r\n",id1,id2);
    163.     delay_ms(100);
    164.     yuyy_soft_spi_cs(0);
    165.     yuyy_soft_spi_write_byte(0x9F);
    166.     id1 = yuyy_soft_spi_read_byte();
    167.     id2 = yuyy_soft_spi_read_byte();
    168.     id3 = yuyy_soft_spi_read_byte();
    169.     yuyy_soft_spi_cs(1);
    170.     printf_hid("发送命令0x9F 读取到ID:0x%02X 0x%02X 0x%02X\r\n",id1,id2,id3);
    171.     delay_ms(100);
    172.    
    173.     while(1)
    174.     {
    175.     }
    176. }
    复制代码


    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-12 13:45 , Processed in 0.083517 second(s), 77 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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