- cyhal_i2c_t i2c_obj;
- void APP_I2CInit(void)
- {
- cyhal_i2c_cfg_t cfg = {
- .address = 0,
- .is_slave = false,
- .frequencyhal_hz = 100000,
- };
- cyhal_i2c_init(&i2c_obj,CYBSP_I2C_SDA,CYBSP_I2C_SCL,NULL);
- cyhal_i2c_configure(&i2c_obj,&cfg);
- }
可以看到用了官方的BSP后初始化外设十分的简便,接下来实现OLED驱动代码,这个OLED是SSD1315驱动的,网上可以搜到具体的驱动代码,或者可以看我过往发的帖子,这里就不放完整代码了,只放上I2C通讯部分
- #define YUYY_OLED_SSD1315_I2C_ADDR 0x3C
- uint8_t YUYY_OLED_SSD1315_I2CSendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t cmd,uint8_t *datas,uint8_t datalen)
- {
- uint8_t err = 0;
- err = cyhal_i2c_master_mem_write(oled_ssd1315_dev->i2cx,YUYY_OLED_SSD1315_I2C_ADDR,cmd,1,datas,datalen,1000);
- return err;
- }
- uint8_t YUYY_OLED_SSD1315_SendCmds(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *cmds,uint8_t cmdlen)
- {
- return YUYY_OLED_SSD1315_I2CSendDatas(oled_ssd1315_dev,0x00,cmds,cmdlen);
- }
- uint8_t YUYY_OLED_SSD1315_SendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *datas,uint8_t datalen)
- {
- return YUYY_OLED_SSD1315_I2CSendDatas(oled_ssd1315_dev,0x40,datas,datalen);
- }
点亮OLED显示指定字符串
- YUYY_OLED_SSD1315_DEV_Type oled_dev;
- void APP_OledInit(void)
- {
- oled_dev.i2cx = &i2c_obj;
- YUYY_OLED_SSD1315_Init(&oled_dev);
- YUYY_OLED_SSD1315_ClearScreen(&oled_dev);
- YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0," CYW20829 TEST");
- YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,2,0," I2C OLED");
- YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0," bbs.21ic.com");
- YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,6,0,"Code by yuyy1989");
- }
运行效果
I2C总线上可以挂载多个从设备,接下来就再增加个温湿度传感器,用I2C读取温湿度传感器的数据,并显示在OLED屏幕上
这里用的是DHTC12温湿度传感器,性能如下图
DHTC12驱动代码
- #define DHTC12_I2C_ADDR 0x44
- typedef struct
- {
- uint8_t inited;
- cyhal_i2c_t *i2cx;
- }YUYY_DHTC12_DEV_Type;
- static uint16_t HumA,HumB;
- uint8_t YUYY_DHTC12_WriteCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd)
- {
- uint8_t regs[2];
- regs[0] = (cmd>>8)&0xFF;
- regs[1] = cmd&0xFF;
- return cyhal_i2c_master_write(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,regs,2,1000,true);
- }
- uint8_t YUYY_DHTC12_ReadDatas(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint8_t *rdatas,uint8_t rlen)
- {
- return cyhal_i2c_master_read(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,rdatas,rlen,1000,true);
- }
- uint8_t YUYY_DHTC12_ReadCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd,uint8_t *rdatas,uint8_t rlen)
- {
- uint8_t regs[2];
- regs[0] = (cmd>>8)&0xFF;
- regs[1] = cmd&0xFF;
- cyhal_i2c_master_write(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,regs,2,1000,false);
- return cyhal_i2c_master_read(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,rdatas,rlen,1000,true);
- }
- //初始化,获取湿度运算系数
- uint8_t YUYY_DHTC12_Init(YUYY_DHTC12_DEV_Type *dhtc12_dev)
- {
- uint8_t x,err = 0,retry = 3;
- dhtc12_dev->inited = 0;
- //复位传感器
- err = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x30A2);
- err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD208,&x,1);
- HumA = (x<<8)&0xFF00;
- err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD209,&x,1);
- HumA |= x;
-
- err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD20A,&x,1);
- HumB = (x<<8)&0xFF00;
- err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD20B,&x,1);
- HumB |= x;
- //HumA=0x7168; HumB=0x2D73;
- //ReadDatSH[6]={0xF3, 0xA9, 0xC0, 0x41, 0xB4, 0x87}
- //27.6 48.4%
- dhtc12_dev->inited = 1;
- return 0;
- }
- const uint16_t POLYNOMIAL = 0x131; //P(x)=x^8+x^5+x^4+1 = 100110001
- uint8_t YUYY_DHTC12_CheckCrc(uint8_t Data[], uint8_t nbrOfBytes)
- {
- uint8_t crc = 0xff; //0
- uint8_t byteCtr,Bit;
- //calculates 8-Bit checksum with given polynomial
- for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
- {
- crc ^= (Data[byteCtr]);
- for (Bit = 8; Bit > 0; --Bit)
- {
- if (crc & 0x80)
- crc = (crc << 1) ^ POLYNOMIAL;
- else
- crc = (crc << 1);
- }
- }
- if (crc != Data[nbrOfBytes])
- {
- Data[nbrOfBytes] = crc;
- return 0x01;
- }
- else
- return 0;
- }
- //单次触发温湿度测量
- uint8_t YUYY_DHTC12_ReadHT(YUYY_DHTC12_DEV_Type *dhtc12_dev,int16_t *tem,int16_t *hum)
- {
- uint8_t i=0,errRe,ReadDatSH[6],CalCRC[3],errorflag=0;
- int16_t TemBuf;
- uint16_t CapBuf;
- errRe = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x2C10);
- if(errRe)
- errRe = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x2C10);
- if(errRe)
- {
- return 0x10|errRe; //发送命令失败
- }
-
- Cy_SysLib_Delay(100);
- errRe = YUYY_DHTC12_ReadDatas(dhtc12_dev,ReadDatSH,6);
- if(errRe)
- {
- return 0x20|errRe; //接收数据失败
- }
- CalCRC[0] = ReadDatSH[0];
- CalCRC[1] = ReadDatSH[1];
- CalCRC[2] = ReadDatSH[2];
- errorflag = YUYY_DHTC12_CheckCrc(CalCRC,2);
- if(errorflag==0)
- {
- TemBuf = (int16_t)(((ReadDatSH[0]<<8)&0xFF00)|ReadDatSH[1]);
- *tem = TemBuf*10/256 + 400;
- }
- CalCRC[0] = ReadDatSH[3];
- CalCRC[1] = ReadDatSH[4];
- CalCRC[2] = ReadDatSH[5];
- errorflag <<= 1;
- errorflag |= YUYY_DHTC12_CheckCrc(CalCRC,2);
- if(errorflag==0)
- {
- CapBuf = (uint16_t)(((ReadDatSH[3]<<8)&0xFF00)|ReadDatSH[4]);
- *hum = (CapBuf-HumB)*600/(HumA-HumB)+300;
- //20℃为5个湿度点 即1℃为0.25个湿度点 0.1℃为0.025
- *hum = *hum+ 2.5*(*tem-250);
- if(*hum>1000)
- *hum = 999;
- else if(*hum<0)
- *hum = 0;
- }
- return errorflag;
- }
初始化,读取温湿度并显示在OLED上
- YUYY_DHTC12_DEV_Type dhtc12_dev;
- void APP_DHTC12Init(void)
- {
- dhtc12_dev.i2cx = &i2c_obj;
- YUYY_DHTC12_Init(&dhtc12_dev);
- }
- int main(void)
- {
- cy_rslt_t result;
- uint8_t printf_count = 0;
- int16_t temp,humi;
- char out[20];
- result = cybsp_init();
- if (result != CY_RSLT_SUCCESS)
- {
- CY_ASSERT(0);
- }
- app_uart_init();
- APP_I2CInit();
- printf("APP Start\n");
- /* Enable global interrupts */
- __enable_irq();
- for (;;)
- {
- Cy_SysLib_Delay(1000);
- printf_count += 1;
- if(!YUYY_DHTC12_ReadHT(&dhtc12_dev,&temp,&humi))
- {
- sprintf(out,"T:%03.1f H:%03.1f%%\n",temp/10.0,humi/10.0);
- YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,out);
- }
- }
- }
运行效果
除了以上的设备之外,还有很多其他的设备(例如气压传感器、EEPROM、LED驱动器等)可以使用I2C通讯控制,有兴趣的伙伴可以自行尝试