RISC-V技术论坛
直播中

少年阿炳

5年用户 40经验值
擅长:嵌入式技术
私信 关注
[经验]

【南京中科微CSM32RV20开发板试用体验】模拟IIC和硬件IIC的使用点亮0.96OLED屏幕+温湿度读取显示

本次内容包括
1.使用模拟IIC点亮OLED屏幕,并读取DHT11的温湿度显示在OLED屏上
2.硬件IIC非中断的使用

首先是模拟IIC的使用
模拟IIC就是使用单片机控制IO口输出高低电平模拟实际IIC开始,结束,数据发送等的相应规则达到点亮OLED的目的。所以最重要的就是如何配置IO口已经输出高低电平。
将需要的IO口配置成输出模式
  1.     GPIO_PULL_Init(GPIOA,PIN7,GPIO_PULLUP);
  2.     GPIO_MODE_Init(GPIOA,PIN7,GPIO_MODE_OUTPUT); //SDA  GPIO 模式

  3. GPIO_MODE_Init(GPIOA,PIN5,GPIO_MODE_OUTPUT); // SCL GPIO 模式
  4.     GPIO_PULL_Init(GPIOA,PIN5,GPIO_PULLUP);
使用GPIO_Write()函数输出高/低电平
  1. //#define                 OLED_SCLK_Set()                        GPIO_Write(GPIOA,PIN5,GPIO_SET)//PA5(SCL)输出高
  2. //#define                        OLED_SCLK_Clr()                        GPIO_Write(GPIOA,PIN5,GPIO_RESET)        //PA5(SCL)输出低
  3. //#define                        OLED_SDIN_Set()                        GPIO_Write(GPIOA,PIN7,GPIO_SET)        //PA7(SDA)输出高
  4. //#define                        OLED_SDIN_Clr()                        GPIO_Write(GPIOA,PIN7,GPIO_RESET)        //PA7(SDA)输出高
  5. //#define                 OLED_READ_SDIN()                GPIO_Read(GPIOA, PIN7)        //读取PA7(SDA)电平

之后就是模拟开始信号,结束信号,响应信号,数据发送,命令发送等。我这里是将现成可用的STM32代码移植过来,然后做了对应的修改。详细可以查看附件1.
特别说明:我这里的响应信号也是模拟的,并不是真读取OLED的返回。

DHT11温湿度的读取
DHT11的数据是通过单总线实现的。数据读取信号以及返回的温湿度值都是通过一根数据线完成,因此需要对同一个IO口先进行输出配置,然后进行输入配置。
  1. // DTH11  ---> PB6
  2. // 输出模式
  3. void DHT11_OUT(void)
  4. {
  5.     GPIO_MODE_Init(GPIOB,PIN6,GPIO_MODE_OUTPUT); //GPIO 模式
  6.     GPIO_PULL_Init(GPIOB,PIN6,GPIO_PULLUP); //GPIO 上拉//PB6
  7. }

  8. // 输入模式
  9. void DHT11_IN(void)
  10. {
  11.     GPIO_MODE_Init(GPIOB,PIN6,GPIO_MODE_INPUT); //GPIO 模式
  12.     GPIO_PULL_Init(GPIOB,PIN6,GPIO_PULLUP); //GPIO

  13. }


硬件IIC使用的注意事项
在用模拟IIC点亮OLED后,我寻思着使用以下CSM32自带的硬件IIC点亮OLED,
使用的是非中断模式,启动硬件IIC使用的I2C_Init_case1()函数。
  1. void I2C_Init_case1(void)//非中断模式
  2. {
  3.     GPIO_MODE_Init(GPIOA, PIN7,  GPIO_MODE_AF);
  4.         GPIO_MODE_Init(GPIOA, PIN8,  GPIO_MODE_AF);

  5.         GPIO_AF_Init(GPIOA,  PIN7,  GPIO_AF0); //SCL
  6.         GPIO_AF_Init(GPIOA,  PIN8,  GPIO_AF0); //SDA

  7.         GPIO_PULL_Init(GPIOA, PIN7,GPIO_PULLUP);
  8.         GPIO_PULL_Init(GPIOA, PIN8,GPIO_PULLUP);

  9.     I2C->CTRL =  1<<12    //时钟分频:0-不分频,1-2分频
  10.                 |0<<9     //error中断:0-关闭,1-开启
  11.                 |0<<8     //ready中断:0-关闭,1-开启
  12.                 |0<<7     //时钟频率:0-100K,1-400K
  13.                 |0x3C;    //从机地址

  14. }

特别说明一下从机地址的配置形式,因为此线使用模式IIC时从机地址都是0x78,所以到了硬件IIC,我想当然配置成了0x78,这样是错误的。
从机地址的bit0位需要根据READ或者WRITE分别配置成1/0
一开始我将地址配置成0x78后,通过逻辑分析仪读取到的SDA变成了0xF0(11110000),也就是0x78(01111000)左移了一位,也就是说CSM32的硬件IIC将我的地址左移了一位,然后在bit0插入了一位0。所以在初始化配置时,需要将从机地址配置成0x3C,这样才能确保从机地址正确。
之后通过I2C_Write函数写数据。
  1. void I2C_Write(uint8_t addr,uint8_t data)//适用于非中断模式
  2. {
  3.         uint32_t i2c_rw_en = 0x0<<16; //i2c操作:0-写操作,1-读操作
  4.         uint32_t i2c_addr = addr<<8;  //存储单元地址
  5.         uint32_t i2c_rwdata = data;   //数据

  6.         I2C->STATUS1 = 0; //清除状态标志
  7.         I2C->DATA = i2c_addr|i2c_rw_en|i2c_rwdata;//写数据

  8.     while(!(I2C->STATUS1&0x01));

  9.         I2C->STATUS1 = 0;
  10. }
I2C_Write(uint8_t addr,uint8_t data)

addr参数,实际代表的是数据命令,对应的就是模拟IIC发送时,中间的那位数据,
0x00,写入命令。0x40,写入数据。
  1. void OLED_Write_IIC_Command(u8 IIC_Command)
  2. {
  3.     I2C_Write(0x00,IIC_Command);

  4. }

  5. /**********************************************
  6. // IIC Write Data
  7. **********************************************/
  8. void OLED_Write_IIC_Data(u8 IIC_Data)
  9. {
  10.     I2C_Write(0x40,IIC_Data);
  11. }
完成以上修改后,就能将之前模拟IIC修改为硬件IIC。

下面图片中逻辑分析仪的时序图供大家参考,截图框内是错误配置的从机地址。
因为我使用的逻辑分析仪就20几块,显示的从机地址好像不正确,但是波形还是准确的。





  • 3.jpg
  • 2.jpg
  • 40c93b9a48e41c95584ee2fb4f59c3435b492d03.jpg

    硬件IIC.rar (2022-1-25 22:09 上传)

    173.24 KB, 阅读权限: 10, 下载次数: 3

    模拟IIC+DHT11.rar (2022-1-25 22:09 上传)

    261.82 KB, 阅读权限: 10, 下载次数: 4

更多回帖

发帖
×
20
完善资料,
赚取积分