[PIC®/AVR®/dsPIC®产品] 【CuriosityNano测评报告】共三期 第二期 2.IIC+SPI+串口测试

[复制链接]
 楼主| zhangjiantao 发表于 2021-6-15 18:28 | 显示全部楼层 |阅读模式
本帖最后由 zhangjiantao 于 2021-6-15 22:39 编辑

#申请原创#  距离第一次更新已半月有余,趁着端午假期把第二期的测评写下
本次的测评主要针对串口,I2C,SPI等外设进行测评,
测评内容:
1.   读取WQ25Q32的ID测试SPI功能是否可以准确读出ID数据通过串口打印出来
    SPI的配置,用到的函数
2.   I2C测试I2C器件的读写(DS3231,AT24C512)挂在一条总线上,并将读取的内容通过串口2打印出来
       串口的配置,PPS,PMD,寄存器,TRIS寄存器,等 I2C的配置,用到的函数

3.   外部中断测试,利用EVB板上的功能实现外部中断的功能,如果发生外部中断,串口发送(发送内容为:External Interrupt Occurrence)

测评流程

                             
    修改下开发板上的按键,以便测试外部中断(下降沿)                  

     

  测试流程
1.   建立工程用MCC生成初始化代码
         
              引脚选择                                               

      
INT0下降沿选择

系统时钟初始化:选择HF时钟,外部中断引脚选择,初始化配置选择上升沿下降沿,这里进用到INT0,MCC是三个都生成了,可以在代码中修改
串口初始化:使能发送接收,波特率115200(这里的波特率会有个误码率,如果波特率不想有误码率可以再自己的系统中采用11.0592M的晶振),打开接收中断,发送采用查询方式
             
定时器1初始化(上一个PWM测评用了定时器0,这里用定时器1),时钟选择FOSC/4,定时时间选择10ms(115200的波特率,理论上每秒传输115200个bit,换算成字节大概是每秒可以传输11520左右个字节,因此接收一个字节的时间大概是0.1ms不到,这里设置成10ms,认为10ms没有接收到新的数据,则认为1帧数据传输完成,具体的数据可以根据实际的项目进行调整)打开中断,但不使能,主要用在串口清BUFFER的,所以串口接收时打开定时器1,
         
定时器1

      
定时器0
  
    PWM (代码中包含上期的测评内容,把这个也放进来)                                                                                                                     
I2C初始化,时钟选择MFINTOSC(100k)主模式,满足大多数I2C从设备的时钟要求,
                     
SPI初始化,时钟选择FOSC/4,SPI波特率0x9F(SPI时钟的计算为SPI_FOSC/2*(BGR+1)),注意TXR,RXR位置1

                     
⑥ 重新定义putch,以便使用 printf,只需再定义的地方,引用头文件#include <stdio.h>,printf很好用,输出各种格式的字符,具体的使用大全和输出格式可百度



测试APP的代码和函数
如下
以下几张图是测试用到的器件一些关键性的参数,比如I2C的地址,和器件ID命令之类的。个人习惯,测试一个片子喜欢读他的ID号,至少可以验证自己的读写时序是对的


   
       AT24C512 的7位地址0x50           
     
                                
           DS3231 的7位地址0x68  
      
   W25Q32     命令90:读取到的数据应该为 0x EF15



pps配置如下

  1.     U2RXPPS = 0x13;   //RC3->UART2:RX2;   
  2.     RB6PPS = 0x21;   //RB6->I2C1:SCL1;   
  3.     INT0PPS = 0x10;   //RC0->EXT_INT:INT0;   
  4.     RC1PPS = 0x0A;   //RC1->PWM1_16BIT:PWM11;   
  5.     RB4PPS = 0x22;   //RB4->I2C1:SDA1;   
  6.     RC2PPS = 0x13;   //RC2->UART2:TX2;   
  7. //  INT2PPS = 0x12;   //RC2->EXT_INT:INT2;   
  8. //  INT1PPS = 0x11;   //RC1->EXT_INT:INT1;   
  9.     I2C1SCLPPS = 0x0E;   //RB6->I2C1:SCL1;   
  10. //  PWMIN1PPS = 0x13;   //RC3->PWM1_16BIT:PWMIN1;   
  11. //  PWMIN0PPS = 0x15;   //RC5->PWM1_16BIT:PWMIN0;   
  12.     SPI1SC**S = 0x16;   //RC6->SPI1:SCK1;   
  13.     I2C1SDAPPS = 0x0C;   //RB4->I2C1:SDA1;   
  14.     RC5PPS = 0x1C;   //RC5->SPI1:SDO1;   
  15.     RC6PPS = 0x1B;   //RC6->SPI1:SCK1;   
  16.     SPI1SDIPPS = 0x14;   //RC4->SPI1:SDI1;   


测试函数,主函数直接调用即可
  1. #include "APP.h"
  2. //宏定义
  3. #define W25QXX_CS  LATCbits.LATC7
  4. #define DS3231_Addr     0x68
  5. #define AT24C512_Addr   0x50
  6. //本函数内调用的变量
  7. uint8_t AT24C512_TestData[12] = {0x00,0x00,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30};
  8. uint8_t AT24C512_READ_TestData[10] = {0};
  9. uint8_t DS3231_Time_buf[7];
  10. uint8_t DS3231_Write_buf1[8]={0x00,0,30,15,2,15,6,21};
  11. uint8_t DS3231_Write_buf[8];
  12. //函数声明
  13. void SPI_W25Q32_Flash_Test(void);
  14. void I2C_DS3231_AT24C512_Test(void);
  15. uint8_t Num_BCD(uint8_t data);
  16. uint8_t BCD_Num(uint8_t data);
  17. void AT24C512_Write1Byte_Any_Address(i2c1_address_t address, uint16_t Addr,uint8_t data);
  18. uint8_t AT24C512_Read1Byte_Any_Address(i2c1_address_t address, uint16_t Addr);
  19. void External_interrupt_test(void);


  20. void PIC18F16Q40_Test(void)
  21. {
  22.     SPI_W25Q32_Flash_Test();     //SPI测试函数
  23.     I2C_DS3231_AT24C512_Test();//I2C,DS3231,AT24C512
  24.     External_interrupt_test();         //外部按键
  25. }

  26. <b>void SPI_W25Q32_Flash_Test(void)
  27. {
  28.     printf("----------------SPI_W25Q32_Flash_Test---------------------\n\r");
  29.     uint8_t Temp = 0;
  30.     uint8_t W25Q32_ID_Buf[2];
  31.     uint16_t W25Q32_ID;
  32.     W25QXX_CS=0;
  33.     Temp=SPI1_ExchangeByte(0x90); //命令
  34.     Temp=SPI1_ExchangeByte(0x00); //24位地址
  35.     Temp=SPI1_ExchangeByte(0x00);     
  36.     Temp=SPI1_ExchangeByte(0x00);
  37.     W25Q32_ID_Buf[0]=SPI1_ExchangeByte(0x00);//发送无用的数据,可以为任何数据,主要是为了产生时钟SCLK
  38.     W25Q32_ID_Buf[1]=SPI1_ExchangeByte(0x00);
  39.     W25Q32_ID=W25Q32_ID_Buf[0]*256+W25Q32_ID_Buf[1];
  40.     W25QXX_CS=1;
  41.     printf("----------------SPI_W25Q32_Flash_ID:0x%X----------------\n\r",W25Q32_ID);
  42. }

  43. void I2C_DS3231_AT24C512_Test(void)
  44. {
  45.     uint8_t Temp = 0;
  46.     printf("----------------I2C_AT24C512_EEPROM_Test-------------------\n\r");
  47.     printf("----------------I2C_AT24C512_Write--------------------------\n\r");
  48.     printf("AT24C512_Write_DATA:%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n\r",AT24C512_TestData[2],AT24C512_TestData[3],\
  49.                                                                                AT24C512_TestData[4],AT24C512_TestData[5],\
  50.                                                                                AT24C512_TestData[6],AT24C512_TestData[7],\
  51.                                                                                AT24C512_TestData[8],AT24C512_TestData[9],\
  52.                                                                                AT24C512_TestData[10],AT24C512_TestData[11]);
  53.     I2C1_WriteNBytes(AT24C512_Addr, AT24C512_TestData, sizeof(AT24C512_TestData));
  54.     DELAY_milliseconds(10);
  55.     printf("----------------I2C_AT24C512_Read-----------------------------\n\r");
  56.     I2C1_WriteNBytes(AT24C512_Addr, AT24C512_TestData, 2);
  57.     I2C1_ReadNBytes(AT24C512_Addr, AT24C512_READ_TestData,sizeof(AT24C512_READ_TestData));   
  58.     printf("AT24C512_Read_DATA:%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n\r", AT24C512_READ_TestData[0],AT24C512_READ_TestData[1],\
  59.                                                                                AT24C512_READ_TestData[2],AT24C512_READ_TestData[3],\
  60.                                                                                AT24C512_READ_TestData[4],AT24C512_READ_TestData[5],\
  61.                                                                                AT24C512_READ_TestData[6],AT24C512_READ_TestData[7],\
  62.                                                                                AT24C512_READ_TestData[8],AT24C512_READ_TestData[9]);
  63.     printf("----------------Write data to any address----------------------------\n\r");
  64.    
  65.     printf("----------------Write 0x45 to 0x1001----------------------------\n\r");
  66.     AT24C512_Write1Byte_Any_Address(AT24C512_Addr, 0x1001,0x45);
  67.     DELAY_milliseconds(10);
  68.     printf("----------------Read data From any address----------------------------\n\r");
  69.     printf("----------------Read data From 0x1001----------------------------\n\r");
  70.     Temp = AT24C512_Read1Byte_Any_Address(AT24C512_Addr, 0x1001);
  71.     printf("----------------address 0x1001 data:0x%X----------------\n\r",Temp);
  72.     printf("----------------I2C_AT24C512_EEPROM_Test OVER-------------------\n\r");
  73.     printf("----------------Read time From DS3231----------------------------\n\r");
  74.     I2C1_ReadDataBlock(DS3231_Addr,0,DS3231_Time_buf,7);
  75.     printf("DS321_time:20%d.%d.%d  %d:%d:%d\t%d\n\r", BCD_Num(DS3231_Time_buf[6]),BCD_Num(DS3231_Time_buf[5]),\
  76.                                                        BCD_Num(DS3231_Time_buf[4]),BCD_Num(DS3231_Time_buf[2]),\
  77.                                                        BCD_Num(DS3231_Time_buf[1]),BCD_Num(DS3231_Time_buf[0]),\
  78.                                                        BCD_Num(DS3231_Time_buf[3]));
  79.    
  80.     printf("Write time:2021.06.15 15:30:00 Tue to DS3231----------------------------\n\r");
  81.     DS3231_Write_buf[0]=Num_BCD(DS3231_Write_buf1[0]);
  82.     DS3231_Write_buf[1]=Num_BCD(DS3231_Write_buf1[1]);
  83.     DS3231_Write_buf[2]=Num_BCD(DS3231_Write_buf1[2]);
  84.     DS3231_Write_buf[3]=Num_BCD(DS3231_Write_buf1[3]);
  85.     DS3231_Write_buf[4]=Num_BCD(DS3231_Write_buf1[4]);
  86.     DS3231_Write_buf[5]=Num_BCD(DS3231_Write_buf1[5]);
  87.     DS3231_Write_buf[6]=Num_BCD(DS3231_Write_buf1[6]);
  88.     DS3231_Write_buf[7]=Num_BCD(DS3231_Write_buf1[7]);
  89.     I2C1_WriteNBytes(DS3231_Addr, DS3231_Write_buf, 8);
  90.     DELAY_milliseconds(10);
  91.      I2C1_ReadDataBlock(DS3231_Addr,0,DS3231_Time_buf,7);
  92.     printf("DS321_time:20%d.%d.%d  %d:%d:%d\t%d\n\r", BCD_Num(DS3231_Time_buf[6]),BCD_Num(DS3231_Time_buf[5]),\
  93.                                                        BCD_Num(DS3231_Time_buf[4]),BCD_Num(DS3231_Time_buf[2]),\
  94.                                                        BCD_Num(DS3231_Time_buf[1]),BCD_Num(DS3231_Time_buf[0]),\
  95.                                                        BCD_Num(DS3231_Time_buf[3]));
  96.     printf("----------------I2C Test over----------------------------\n\r");
  97. }</b>

  98. /****************************************************************************
  99. * 功    能:10进制数据转换为BCD码
  100. * 名    称:Num_BCD(uint8_t data)
  101. * 说    明:用在时钟DS3231处。
  102. ****************************************************************************/
  103. uint8_t Num_BCD(uint8_t data)
  104. {
  105.     uint8_t i,j,k;
  106.     i=data/10;
  107.     j=data%10;
  108.     k=j+(i<<4);
  109.     return k;
  110. }

  111. /****************************************************************************
  112. * 功    能:BCD码转换为10进制数据
  113. * 名    称:BCD_Num(uint8_t data)
  114. * 说    明:用在时钟DS3231处。
  115. ****************************************************************************/
  116. uint8_t BCD_Num(uint8_t data)
  117. {
  118.     uint8_t i;
  119.     i=data&0x0F;
  120.     data=data>>4;
  121.     data&=0x0F;
  122.     data*=10;
  123.     i+=data;
  124.     return i;
  125. }

  126. <b>void putch( char byte)//将串口跟 printf() 联系起来即重定向printf函数
  127. {

  128.     U2CON0bits.TXEN=1;
  129.     while(!UART2_is_tx_ready());
  130.     U2TXB=byte;
  131.     U2CON0bits.TXEN=0;
  132. }</b>

  133. void AT24C512_Write1Byte_Any_Address(i2c1_address_t address, uint16_t Addr,uint8_t data)
  134. {
  135.     uint8_t databuf[3];
  136.     databuf[0]=(uint8_t)(Addr/256);
  137.     databuf[1]=(uint8_t)(Addr%256);
  138.     databuf[2]=data;
  139.     while(!I2C1_Open(address)); // sit here until we get the bus..
  140.     I2C1_SetBuffer(databuf,3);
  141.     I2C1_SetAddressNackCallback(NULL,NULL); //NACK polling?
  142.     I2C1_MasterWrite();
  143.     while(I2C1_BUSY == I2C1_Close()); // sit here until finished.
  144. }
  145. uint8_t AT24C512_Read1Byte_Any_Address(i2c1_address_t address, uint16_t Addr)
  146. {
  147.     uint8_t AddrBuf[2];
  148.     uint8_t TEM=0;
  149.     AddrBuf[0]=Addr/256;
  150.     AddrBuf[1]=(uint8_t)(Addr%256);
  151.     I2C1_WriteNBytes(address, AddrBuf, 2);
  152.     I2C1_ReadNBytes(address, &TEM, 1);
  153.     return TEM;
  154. }

  155. void External_interrupt_test(void)
  156. {
  157.     printf("MCU sleep when the external interrupt wakes up to continue to execute\n\r");
  158.     asm("SLEEP"); //休眠模式
  159.     NOP();
  160.     NOP();
  161.     printf("------------- KEY-------------------\n\r");
  162.    
  163. }



测试效果如下:
  1.  读取到正确的W25Q32 的ID:0xEF15  并通过串口打印出来
  2.  写入数据并读取出来,测试数据的写入和读取  并通过串口打印出来
  3. 以上两步执行完成,直接休眠直到外部中断唤醒(外部中断唤醒发送:External Interrupt Occurrence)

上期的PWM呼吸灯也在此部分代码里,一并上传,MCC趋势很方便,生成的可以跑起来,具体的实现可以通过函数的调用来实现功能


代码



视频不太会插,研究好了再插入视频,先上张图
                                 













本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
chenqianqian 发表于 2021-6-15 20:22 来自手机 | 显示全部楼层
讲解详细,赞一个。
51xlf 发表于 2021-7-3 16:42 | 显示全部楼层
使用的是硬件的吗?   

评论

硬件的  发表于 2021-7-6 21:42
i1mcu 发表于 2021-7-3 16:42 | 显示全部楼层
IIC最大速率是多少   
pmp 发表于 2021-7-3 16:43 | 显示全部楼层
做个逻。辑。 分析仪吧
mmbs 发表于 2021-7-3 16:43 | 显示全部楼层
读取flash的效果怎样   
1988020566 发表于 2021-7-3 16:43 | 显示全部楼层
讲解详细,赞一个。  
lzbf 发表于 2021-7-3 16:43 | 显示全部楼层
测评的效果不错啊。      
houjiakai 发表于 2021-7-3 16:44 | 显示全部楼层
能够做U盘吗?        
jimmhu 发表于 2021-7-3 16:44 | 显示全部楼层
            
cemaj 发表于 2021-7-3 16:44 | 显示全部楼层
最大的频率是多少        
youtome 发表于 2021-7-3 16:44 | 显示全部楼层
能够解析json数组吗?         

评论

可以 解析,可能比较复杂 用八位的MCU来实现  发表于 2021-7-6 21:45
凯复Kane 发表于 2021-7-7 14:59 来自手机 | 显示全部楼层
好详细的测评 流程可以参考一下吗 以后我测评就按这个来了
usysm 发表于 2021-8-7 12:14 | 显示全部楼层
单片机模拟SPI的?
typeof 发表于 2021-8-7 12:15 | 显示全部楼层
pic单片机通过IIC对24c02写操作
yujielun 发表于 2021-8-7 12:16 | 显示全部楼层
spi和I2c的速率是多少?
kkzz 发表于 2021-8-7 12:16 | 显示全部楼层
总结的非常不错。
pklong 发表于 2021-8-7 12:17 | 显示全部楼层
怎么确定pic单片机工作在spi还是i2c模式  
touser 发表于 2021-8-7 12:17 | 显示全部楼层
rs232速率一般最大115200  
myiclife 发表于 2021-8-7 12:18 | 显示全部楼层
接触比较多的是IIC和SPI接口
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

55

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部