[活动] 【APM32F411V Tiny Board测评】4.I2C点亮OLED和读取温湿度传感器数据

[复制链接]
1271|1
 楼主| yuyy1989 发表于 2024-5-11 23:10 | 显示全部楼层 |阅读模式
原本想用硬件驱动的,结果和评测407时一样总是搞不定,官方的bsp_i2c也是用的模拟I2C,官网搜I2C相关文档也只能搜到模拟I2C与EEPROM通讯的,最后放弃改用软件模拟I2C
选用PB6和PB7作为SCL和SDA,初始化为开漏输出模式
  1. YUYY_SOFTIIC_DEV_Type siic;
  2. void app_SoftI2cInit()
  3. {
  4.     GPIO_Config_T gpioConfigStruct;
  5.     RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
  6.     GPIO_ConfigStructInit(&gpioConfigStruct);
  7.     gpioConfigStruct.mode = GPIO_MODE_OUT;
  8.     gpioConfigStruct.speed = GPIO_SPEED_100MHz;
  9.     gpioConfigStruct.pin = GPIO_PIN_6 | GPIO_PIN_7;
  10.     gpioConfigStruct.otype = GPIO_OTYPE_OD;
  11.     gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
  12.     GPIO_Config(GPIOB, &gpioConfigStruct);
  13.    
  14.     siic.scl.gpio = GPIOB;
  15.     siic.scl.pin = GPIO_PIN_6;
  16.     siic.sda.gpio = GPIOB;
  17.     siic.sda.pin = GPIO_PIN_7;
  18.     YUYY_SOFTIIC_Init(&siic);
  19. }
模拟I2C代码

  1. #define YUYY_SOFT_IIC_ACK 0
  2. #define YUYY_SOFT_IIC_NACK 1

  3. #define YUYY_SOFT_IIC_PIN_SDA 0
  4. #define YUYY_SOFT_IIC_PIN_SCL 1


  5. void YUYY_SOFTIIC_GPIO_INOUT(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t pin,uint8_t inout)
  6. {
  7.     if(pin == YUYY_SOFT_IIC_PIN_SDA)
  8.         iicx->gpio_inout_func(&(iicx->sda),inout);
  9.     else if(pin == YUYY_SOFT_IIC_PIN_SCL)
  10.         iicx->gpio_inout_func(&(iicx->scl),inout);
  11. }

  12. void YUYY_SOFTIIC_GPIO_SETLEV(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t pin,YUYY_GPIO_LEV_TYPE lev)
  13. {
  14.     if(pin == YUYY_SOFT_IIC_PIN_SDA)
  15.         iicx->gpio_setlev_func(&(iicx->sda),lev);
  16.     else if(pin == YUYY_SOFT_IIC_PIN_SCL)
  17.         iicx->gpio_setlev_func(&(iicx->scl),lev);
  18. }

  19. YUYY_GPIO_LEV_TYPE YUYY_SOFTIIC_GPIO_GETLEV(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t pin)
  20. {
  21.     if(pin == YUYY_SOFT_IIC_PIN_SDA)
  22.         return iicx->gpio_getlev_func(&(iicx->sda));
  23.     else if(pin == YUYY_SOFT_IIC_PIN_SCL)
  24.         return iicx->gpio_getlev_func(&(iicx->scl));
  25.     return YUYY_GPIO_LEV0;
  26. }

  27. void YUYY_SOFTIIC_DELAYMS(YUYY_SOFTIIC_DEV_Type *iicx,uint32_t delay)
  28. {
  29.     iicx->iic_delayus_func(delay);
  30. }

  31. uint8_t YUYY_SOFTIIC_WaitScl_Timeout(YUYY_SOFTIIC_DEV_Type *iicx,YUYY_GPIO_LEV_TYPE lev)
  32. {
  33.     uint8_t i = 0;
  34.     while(YUYY_SOFTIIC_GPIO_GETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL) != YUYY_GPIO_LEV1)
  35.     {
  36.         i += 1;
  37.         if (i == 10)
  38.         {
  39.             return 1;
  40.         }
  41.         YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  42.     }
  43.     return 0;
  44. }


  45. uint8_t YUYY_SOFTIIC_Start(YUYY_SOFTIIC_DEV_Type *iicx)
  46. {
  47.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
  48.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  49.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
  50.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  51.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
  52.     if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
  53.         return 1;

  54.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  55.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  56.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
  57.     YUYY_SOFTIIC_DELAYMS(iicx,5*iicx->iic_delay_time);
  58.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
  59.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  60.     return YUYY_SOFTIIC_OK;
  61. }

  62. uint8_t YUYY_SOFTIIC_Stop(YUYY_SOFTIIC_DEV_Type *iicx)
  63. {
  64.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
  65.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  66.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
  67.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  68.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
  69.     if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
  70.         return 1;

  71.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  72.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  73.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
  74.     return YUYY_SOFTIIC_OK;
  75. }

  76. uint8_t YUYY_SOFTIIC_ReadACK(YUYY_SOFTIIC_DEV_Type *iicx)
  77. {
  78.     uint8_t i=0,ack=YUYY_SOFT_IIC_ACK;
  79.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODIN);
  80.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  81.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
  82.     if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
  83.         return 1;
  84.    
  85.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  86.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  87.     while(YUYY_SOFTIIC_GPIO_GETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA)!=YUYY_GPIO_LEV0 && i<10)
  88.     {
  89.         YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  90.         i += 1;
  91.     }
  92.     if(i>8)
  93.         ack = YUYY_SOFT_IIC_NACK;
  94.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
  95.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  96.     return ack;
  97. }

  98. uint8_t YUYY_SOFTIIC_SendACK(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t ack)
  99. {
  100.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
  101.     if(ack == YUYY_SOFT_IIC_ACK)
  102.         YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
  103.     else
  104.         YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
  105.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  106.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
  107.     if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
  108.         return 1;
  109.    
  110.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  111.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  112.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
  113.     YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  114.     return YUYY_SOFTIIC_OK;
  115. }

  116. uint8_t YUYY_SOFTIIC_SendByte(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t dat)
  117. {
  118.     uint8_t i = 0;
  119.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
  120.     while(i<8)
  121.     {
  122.         if(dat & 0x80)
  123.             YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
  124.         else
  125.             YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
  126.         YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  127.         YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
  128.         if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
  129.             return 1;
  130.         
  131.         YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  132.         YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  133.         YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
  134.         YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  135.         dat = dat << 1;
  136.         i += 1;
  137.     }
  138.     return YUYY_SOFTIIC_OK;
  139. }

  140. uint8_t YUYY_SOFTIIC_ReadByte(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t *dat)
  141. {
  142.     uint8_t i = 0;
  143.     *dat = 0;
  144.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODIN);
  145.     while(i<8)
  146.     {
  147.         YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  148.         YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
  149.         if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
  150.             return 1;
  151.         
  152.         YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  153.         YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  154.         *dat = *dat << 1;
  155.         if(YUYY_SOFTIIC_GPIO_GETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA) == YUYY_GPIO_LEV1)
  156.             *dat |= 0x01;
  157.         YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
  158.         YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
  159.         i += 1;
  160.     }
  161.     return YUYY_SOFTIIC_OK;
  162. }

  163. void YUYY_SOFTIIC_Init(YUYY_SOFTIIC_DEV_Type *iicx)
  164. {
  165.     if(!iicx->iic_delayus_func)
  166.     {
  167.         iicx->iic_delayus_func = YUYY_DelayUs;
  168.         iicx->iic_delay_time = 1;
  169.     }
  170.     if(!iicx->gpio_inout_func)
  171.         iicx->gpio_inout_func = YUYY_GPIO_ODInOut;
  172.     if(!iicx->gpio_setlev_func)
  173.         iicx->gpio_setlev_func = YUYY_GPIO_SetLev;
  174.     if(!iicx->gpio_getlev_func)
  175.         iicx->gpio_getlev_func = YUYY_GPIO_GetLev;
  176.     //SDA SCL需接上拉电阻,开漏输出
  177.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
  178.     YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
  179.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
  180.     YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
  181.     //YUYY_SOFTIIC_Stop(iicx);
  182. }
  183. //此处设备地址已经过移位处理,最低位0写1读
  184. uint8_t YUYY_SOFTIIC_MasterSendStart(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr)
  185. {
  186.     if(YUYY_SOFTIIC_Start(iicx) != YUYY_SOFTIIC_OK)
  187.         return 1;

  188.     if(YUYY_SOFTIIC_SendByte(iicx,devaddr) != YUYY_SOFTIIC_OK)
  189.         return 2;
  190.    
  191.     if(YUYY_SOFTIIC_ReadACK(iicx) != YUYY_SOFT_IIC_ACK)
  192.         return 3;
  193.     return 0;
  194. }

  195. uint8_t YUYY_SOFTIIC_MasterSendDatasWithOption(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t option,uint8_t *datas,uint16_t datalen)
  196. {
  197.     uint8_t i = 0,err = YUYY_SOFTIIC_OK;
  198.     if(!iicx)
  199.         return 1;
  200.     if(option & YUYY_IIC_SEND_START)
  201.     {
  202.         err = YUYY_SOFTIIC_MasterSendStart(iicx,(devaddr<<1)&0xFE);
  203.         if(err != YUYY_SOFTIIC_OK)
  204.             return err;
  205.     }
  206.     while (i < datalen)
  207.     {
  208.         YUYY_SOFTIIC_SendByte(iicx,datas[i]);
  209.         if(YUYY_SOFTIIC_ReadACK(iicx) != YUYY_SOFT_IIC_ACK)
  210.             return 4;
  211.         i += 1;
  212.     }
  213.     if(option & YUYY_IIC_SEND_STOP)
  214.         YUYY_SOFTIIC_Stop(iicx);
  215.     return YUYY_SOFTIIC_OK;
  216. }
  217. uint8_t YUYY_SOFTIIC_MasterReadDatasWithOption(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t option,uint8_t *datas,uint16_t datalen)
  218. {
  219.     uint8_t i = 0,err = YUYY_SOFTIIC_OK,ack;
  220.     if(!iicx)
  221.         return 1;
  222.     if(option & YUYY_IIC_SEND_START)
  223.     {
  224.         err = YUYY_SOFTIIC_MasterSendStart(iicx,(devaddr<<1)|0x01);
  225.         if(err != YUYY_SOFTIIC_OK)
  226.             return err;
  227.     }
  228.     while (i < datalen)
  229.     {
  230.         if(YUYY_SOFTIIC_ReadByte(iicx,&datas[i]) != YUYY_SOFTIIC_OK)
  231.             return 4;
  232.         if(i==datalen-1)
  233.             ack = YUYY_SOFT_IIC_NACK;
  234.         else
  235.             ack = YUYY_SOFT_IIC_ACK;
  236.         if(YUYY_SOFTIIC_SendACK(iicx,ack) != YUYY_SOFTIIC_OK)
  237.             return 5;
  238.         i += 1;
  239.     }
  240.     if(option & YUYY_IIC_SEND_STOP)
  241.         YUYY_SOFTIIC_Stop(iicx);
  242.     return YUYY_SOFTIIC_OK;
  243. }
  244. uint8_t testerr = 0;

  245. uint8_t YUYY_SOFTIIC_MasterSendRegDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
  246. {
  247.         uint8_t i = 0,ack = YUYY_SOFT_IIC_ACK,err = YUYY_SOFTIIC_OK;
  248.     if(!iicx)
  249.         return 1;
  250.     err = YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START,reg,reglen);
  251.     testerr = err;
  252.     if(err == YUYY_SOFTIIC_OK)
  253.             err = YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_STOP,datas,datalen);
  254.     testerr = err;
  255.         return err;
  256. }
  257. uint8_t YUYY_SOFTIIC_MasterReadRegDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
  258. {
  259.         uint8_t i = 0,ack = YUYY_SOFT_IIC_ACK,err = YUYY_SOFTIIC_OK;
  260.     if(!iicx)
  261.         return 1;
  262.         if(reglen > 0)
  263.         {
  264.         err = YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START,reg,reglen);
  265.         }
  266.         if(err == YUYY_SOFTIIC_OK)
  267.         err = YUYY_SOFTIIC_MasterReadDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
  268.         return err;
  269. }

  270. uint8_t YUYY_SOFTIIC_MasterSendDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *datas,uint16_t datalen)
  271. {
  272.     return YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
  273. }

  274. uint8_t YUYY_SOFTIIC_MasterReadDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *datas,uint16_t datalen)
  275. {
  276.     return YUYY_SOFTIIC_MasterReadDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
  277. }

  278. uint8_t YUYY_SOFTIIC_MasterSendReg8Datas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t reg,uint8_t *datas,uint16_t datalen)
  279. {
  280.     return YUYY_SOFTIIC_MasterSendRegDatas(iicx,devaddr,®,1,datas,datalen);
  281. }
  282. uint8_t YUYY_SOFTIIC_MasterReadReg8Datas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t reg,uint8_t *datas,uint16_t datalen)
  283. {
  284.     return YUYY_SOFTIIC_MasterReadRegDatas(iicx,devaddr,®,1,datas,datalen);
  285. }
OLED驱动代码
  1. #define YUYY_OLED_SSD1315_IIC_ADDR 0x3C
  2. const uint8_t oled_ssd1315_init_cmd[25]=
  3. {
  4.        0xAE,//关闭显示
  5.        0xD5,//设置时钟分频因子,震荡频率
  6.        0x80,  //[3:0],分频因子;[7:4],震荡频率
  7.        0xA8,//设置驱动路数
  8.        0X3F,//默认0X3F(1/64)
  9.        0xD3,//设置显示偏移
  10.        0X00,//默认为0
  11.        0x40,//设置显示开始行 [5:0],行数.                              
  12.        0x8D,//电荷泵设置
  13.        0x14,//bit2,开启/关闭
  14.        0x20,//设置内存地址模式
  15.        0x02,//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
  16.        0xA1,//段重定义设置,bit0:0,0->0;1,0->127;
  17.        0xC8,//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
  18.        0xDA,//设置COM硬件引脚配置
  19.        0x12,//[5:4]配置            
  20.        0x81,//对比度设置
  21.        0xEF,//1~255;默认0X7F (亮度设置,越大越亮)
  22.        0xD9,//设置预充电周期
  23.        0xF1,//[3:0],PHASE 1;[7:4],PHASE 2;
  24.        0xDB,//设置VCOMH 电压倍率
  25.        0x30,//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
  26.        0xA4,//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
  27.        0xA6,//设置显示方式;bit0:1,反相显示;0,正常显示        
  28.        0xAF,//开启显示     
  29. };

  30. uint8_t YUYY_OLED_SSD1315_IICSendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t cmd,uint8_t *datas,uint8_t datalen)
  31. {
  32.     uint8_t err = 0;
  33.     if(!oled_ssd1315_dev->iic_senddatas_func)
  34.         return 1;
  35.     err = oled_ssd1315_dev->iic_senddatas_func(oled_ssd1315_dev->iicx,YUYY_OLED_SSD1315_IIC_ADDR,cmd,datas,datalen);
  36.     return err;
  37. }

  38. uint8_t YUYY_OLED_SSD1315_SendCmds(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *cmds,uint8_t cmdlen)
  39. {
  40.     return YUYY_OLED_SSD1315_IICSendDatas(oled_ssd1315_dev,0x00,cmds,cmdlen);
  41. }

  42. uint8_t YUYY_OLED_SSD1315_SendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *datas,uint8_t datalen)
  43. {
  44.     return YUYY_OLED_SSD1315_IICSendDatas(oled_ssd1315_dev,0x40,datas,datalen);
  45. }

  46. uint8_t YUYY_OLED_SSD1315_SetPageCol(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t page,uint8_t col)
  47. {
  48.     uint8_t cmds[3];
  49.     if(page < 8 && col < 128)
  50.     {
  51.         cmds[0] = 0xB0+page;
  52.         cmds[1] = 0x10|(col>>4);
  53.         cmds[2] = 0x00|(col&0x0f);
  54.         return YUYY_OLED_SSD1315_SendCmds(oled_ssd1315_dev,cmds,3);
  55.     }
  56.     return 1;
  57. }

  58. uint8_t YUYY_OLED_SSD1315_ClearScreen(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev)
  59. {
  60.     uint8_t i=0,datas[128]={0};
  61.     while(i<8)
  62.     {
  63.         if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,i,0))
  64.             return 1;
  65.         if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,128))
  66.             return 1;
  67.         i += 1;
  68.     }
  69.     return 0;
  70. }

  71. uint8_t YUYY_OLED_SSD1315_TestScreen(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t d1,uint8_t d2)
  72. {
  73.     uint8_t i=0,datas[128]={0};
  74.     while (i < 128)
  75.     {
  76.         datas[i] = d1;
  77.         datas[i+1] = d2;
  78.         i += 2;
  79.     }
  80.     i = 0;
  81.     while(i<8)
  82.     {
  83.         if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,i,0))
  84.             return 1;
  85.         if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,128))
  86.             return 1;
  87.         i += 1;
  88.     }
  89.     return 0;
  90. }

  91. uint8_t YUYY_OLED_SSD1315_Init(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev)
  92. {
  93.     uint8_t err = 0;
  94.     err = YUYY_OLED_SSD1315_SendCmds(oled_ssd1315_dev,(uint8_t *)oled_ssd1315_init_cmd,25);
  95.     return err;
  96. }

  97. void YUYY_OLED_SSD1315_CopyDatas(uint8_t *dst,uint8_t *src,uint8_t len,uint8_t rev)
  98. {
  99.     uint8_t i = 0;
  100.     while (i < len)
  101.     {
  102.         if(rev)
  103.             dst[i] = ~src[i];
  104.         else
  105.             dst[i] = src[i];
  106.         i += 1;
  107.     }
  108. }


  109. void YUYY_OLED_SSD1315_DisplayDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,uint8_t *dp,uint8_t width,uint8_t height)
  110. {
  111.     uint8_t rev,i=0,j=0,k=0,hp=height/8;
  112.     uint8_t datas[128] = {0};
  113.     rev = option&YUYY_FONT_DATAS_REVERSE;
  114.     if((option&YUYY_FONT_DATAS_COL_COL) == 0)
  115.     {
  116.         while (i<hp)
  117.         {
  118.             if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+i,column))
  119.                 return;
  120.             YUYY_OLED_SSD1315_CopyDatas(datas,dp,width,rev);
  121.             if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,width))
  122.                 return;
  123.             i+=1;
  124.         }
  125.     }
  126.     else
  127.     {
  128.         while (i<hp)
  129.         {
  130.             if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+i,column))
  131.                 return;
  132.             k=i;
  133.             j=0;
  134.             while (j<width)
  135.             {
  136.                 if(rev == 0)
  137.                     datas[j] == dp[k];
  138.                 else
  139.                     datas[j] == ~dp[k];
  140.                 j+=1;
  141.                 k+=hp;
  142.             }
  143.             if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,width))
  144.                 return;
  145.             i+=1;
  146.         }
  147.     }
  148. }

  149. void YUYY_OLED_SSD1315_DisplayString8x16(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
  150. {
  151.     uint8_t i=0,j = 0,rev = option&YUYY_FONT_DATAS_REVERSE;
  152.     uint8_t datas1[128] = {0},datas2[128] = {0};
  153.    
  154.     while(text[i]>0x00 && j < 128)
  155.     {
  156.         if((text[i] > 0x1F)&&(text[i] < 0x7F))
  157.         {
  158.             YUYY_OLED_SSD1315_CopyDatas(&datas1[j],(uint8_t *)&YUYY_FONT_ASCII_TABLE_8x16[text[i]-0x20][0],8,rev);
  159.             YUYY_OLED_SSD1315_CopyDatas(&datas2[j],(uint8_t *)&YUYY_FONT_ASCII_TABLE_8x16[text[i]-0x20][8],8,rev);
  160.         }
  161.         j += 8;
  162.         i += 1;
  163.     }
  164.     if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page,column))
  165.         return;
  166.     if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas1,j))
  167.         return;
  168.     if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+1,column))
  169.         return;
  170.     if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas2,j))
  171.         return;
  172. }

  173. void YUYY_OLED_SSD1315_DisplayString6x8(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
  174. {
  175.     uint8_t i=0,j = 0,rev = option&YUYY_FONT_DATAS_REVERSE;
  176.     uint8_t datas[128] = {0};
  177.     while(text[i]>0x00 && j < 128)
  178.     {
  179.         if((text[i] > 0x1F)&&(text[i] < 0x7F))
  180.         {
  181.             if(j < 126)
  182.                 YUYY_OLED_SSD1315_CopyDatas(&datas[j],(uint8_t *)YUYY_FONT_ASCII_TABLE_6x8[text[i]-0x20],6,rev);
  183.             else
  184.                 YUYY_OLED_SSD1315_CopyDatas(&datas[j],(uint8_t *)YUYY_FONT_ASCII_TABLE_6x8[text[i]-0x20],2,rev);
  185.         }
  186.         j += 6;
  187.         i += 1;
  188.     }
  189.     if(j > 128)
  190.         j = 128;
  191.     if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page,column))
  192.         return;
  193.     if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,j))
  194.         return;
  195. }
初始化OLED
  1. void oled_init()
  2. {
  3. //    oled_dev.iicx = I2C1;
  4. //    oled_dev.iic_senddatas_func = (YUYY_OLED_SSD1315_IICSendDatasFunc_Type)YUYY_HARDIIC_MasterSendReg8Datas;
  5.     oled_dev.iicx = &siic;
  6.     oled_dev.iic_senddatas_func = (YUYY_OLED_SSD1315_IICSendDatasFunc_Type)YUYY_SOFTIIC_MasterSendReg8Datas;
  7.     YUYY_OLED_SSD1315_Init(&oled_dev);
  8.     YUYY_OLED_SSD1315_ClearScreen(&oled_dev);
  9.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0," APM32F411 TEST");
  10.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,2,0,"    I2C OLED");
  11.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,"  bbs.21ic.com");
  12.     YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,6,0,"Code by yuyy1989");
  13. }
运行效果
微信图片_20240511225431.jpg
接下来读取DHTC12的温湿度数据并在OLED上显示出来
DHTC12驱动代码

  1. #define DHTC12_I2C_ADDR 0x44

  2. static uint16_t HumA,HumB;

  3. uint8_t YUYY_DHTC12_WriteCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd)
  4. {
  5.         return dhtc12_dev->iic_sendregdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,cmd,NULL,0);
  6. }

  7. uint8_t YUYY_DHTC12_ReadDatas(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint8_t *rdatas,uint8_t rlen)
  8. {
  9.         return dhtc12_dev->iic_readdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,rdatas,rlen);
  10. }

  11. uint8_t YUYY_DHTC12_ReadCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd,uint8_t *rdatas,uint8_t rlen)
  12. {
  13.         return dhtc12_dev->iic_readregdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,cmd,rdatas,rlen);
  14. }

  15. //初始化,获取湿度运算系数
  16. uint8_t YUYY_DHTC12_Init(YUYY_DHTC12_DEV_Type *dhtc12_dev)
  17. {
  18.     uint8_t x,err = 0,retry = 3;
  19.     dhtc12_dev->inited = 0;
  20.     if(!dhtc12_dev->delayms_func)
  21.         dhtc12_dev->delayms_func = YUYY_DelayMs;
  22.     //复位传感器
  23.     err = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x30A2);
  24.     err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD208,&x,1);
  25.     HumA = (x<<8)&0xFF00;
  26.     err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD209,&x,1);
  27.     HumA |= x;
  28.    
  29.     err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD20A,&x,1);
  30.     HumB = (x<<8)&0xFF00;
  31.     err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD20B,&x,1);
  32.     HumB |= x;
  33.     //HumA=0x7168;  HumB=0x2D73;
  34.     //ReadDatSH[6]={0xF3, 0xA9, 0xC0, 0x41, 0xB4, 0x87}
  35.     //27.6 48.4%
  36.     dhtc12_dev->inited = 1;
  37.     return 0;
  38. }

  39. const uint16_t POLYNOMIAL = 0x131; //P(x)=x^8+x^5+x^4+1 = 100110001

  40. uint8_t YUYY_DHTC12_CheckCrc(uint8_t Data[], uint8_t nbrOfBytes)
  41. {
  42.     uint8_t crc = 0xff; //0
  43.     uint8_t byteCtr,Bit;
  44.     //calculates 8-Bit checksum with given polynomial
  45.     for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
  46.     {
  47.         crc ^= (Data[byteCtr]);
  48.         for (Bit = 8; Bit > 0; --Bit)
  49.         {
  50.             if (crc & 0x80)
  51.                 crc = (crc << 1) ^ POLYNOMIAL;
  52.             else
  53.                 crc = (crc << 1);
  54.         }
  55.     }
  56.     if (crc != Data[nbrOfBytes])
  57.     {
  58.         Data[nbrOfBytes] = crc;
  59.         return 0x01;
  60.     }
  61.     else
  62.         return 0;
  63. }

  64. //单次触发温湿度测量
  65. uint8_t YUYY_DHTC12_ReadHT(YUYY_DHTC12_DEV_Type *dhtc12_dev,int16_t *tem,int16_t *hum)
  66. {
  67.     uint8_t i=0,errRe,ReadDatSH[6],CalCRC[3],errorflag=0;
  68.     int16_t TemBuf;
  69.     uint16_t CapBuf;
  70.     errRe = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x2C10);
  71.     if(errRe)
  72.         errRe = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x2C10);
  73.     if(errRe)
  74.     {
  75.         return 0x10|errRe; //发送命令失败
  76.     }
  77.    
  78.     dhtc12_dev->delayms_func(100);
  79.     errRe = YUYY_DHTC12_ReadDatas(dhtc12_dev,ReadDatSH,6);

  80.     if(errRe)
  81.     {
  82.         return 0x20|errRe; //接收数据失败
  83.     }
  84.     CalCRC[0] = ReadDatSH[0];
  85.     CalCRC[1] = ReadDatSH[1];
  86.     CalCRC[2] = ReadDatSH[2];
  87.     errorflag = YUYY_DHTC12_CheckCrc(CalCRC,2);
  88.     if(errorflag==0)
  89.     {
  90.         TemBuf = (int16_t)(((ReadDatSH[0]<<8)&0xFF00)|ReadDatSH[1]);
  91.         *tem = TemBuf*10/256 + 400;
  92.     }
  93.     CalCRC[0] = ReadDatSH[3];
  94.     CalCRC[1] = ReadDatSH[4];
  95.     CalCRC[2] = ReadDatSH[5];
  96.     errorflag <<= 1;
  97.     errorflag |= YUYY_DHTC12_CheckCrc(CalCRC,2);
  98.     if(errorflag==0)
  99.     {
  100.         CapBuf = (uint16_t)(((ReadDatSH[3]<<8)&0xFF00)|ReadDatSH[4]);
  101.         *hum = (CapBuf-HumB)*600/(HumA-HumB)+300;
  102.         //20℃为5个湿度点  即1℃为0.25个湿度点  0.1℃为0.025
  103.         *hum = *hum+ 2.5*(*tem-250);
  104.         if(*hum>1000)
  105.             *hum = 999;
  106.         else if(*hum<0)
  107.             *hum = 0;
  108.     }
  109.     return errorflag;       
  110. }
DHTC12初始化
  1. YUYY_DHTC12_DEV_Type dhtc12_dev;
  2. void dhtc12_init()
  3. {
  4. //    dhtc12_dev.iicx = I2C1;
  5.     dhtc12_dev.iicx = &siic;
  6.     dhtc12_dev.delayms_func = YUYY_DelayMs;
  7. //    dhtc12_dev.iic_readdatas_func = (YUYY_DHTC12_IICReadDatasFunc_Type)YUYY_HARDIIC_MasterReadDatas;
  8. //    dhtc12_dev.iic_readregdatas_func = (YUYY_DHTC12_IICReadReg16BEDatasFunc_Type)YUYY_HARDIIC_MasterReadReg16BEDatas;
  9. //    dhtc12_dev.iic_sendregdatas_func = (YUYY_DHTC12_IICSendReg16BEDatasFunc_Type)YUYY_HARDIIC_MasterSendReg16BEDatas;
  10.     dhtc12_dev.iic_readdatas_func = (YUYY_DHTC12_IICReadDatasFunc_Type)YUYY_SOFTIIC_MasterReadDatas;
  11.     dhtc12_dev.iic_readregdatas_func = (YUYY_DHTC12_IICReadReg16BEDatasFunc_Type)YUYY_SOFTIIC_MasterReadReg16BEDatas;
  12.     dhtc12_dev.iic_sendregdatas_func = (YUYY_DHTC12_IICSendReg16BEDatasFunc_Type)YUYY_SOFTIIC_MasterSendReg16BEDatas;
  13.     YUYY_DHTC12_Init(&dhtc12_dev);
  14. }
在main函数中调用
  1. int main(void)
  2. {
  3.     uint8_t i = 0;
  4.     int16_t temp,humi;
  5.     char out[20];
  6.     ConfigSysClock();
  7.     yuyy_LedInit();
  8.     tim9_init();
  9. //    pwm_init();
  10.     uart_init();
  11. //    core_main();
  12. //    app_I2CInit();
  13.     //YUYY_HARDIIC_SetInitFunc(app_I2CInit);
  14.     app_SoftI2cInit();
  15.     oled_init();
  16.     dhtc12_init();
  17.     while (1)
  18.     {
  19.         i += 1;
  20. //        printf("极海APM32F411串口Printf测试 by yuyy1989 当前数字是:%d\n",i);
  21.         YUYY_DelayMs(1000);
  22.         yuyy_LedToggle(YUYY_LED2);
  23.         YUYY_DelayMs(1000);
  24.         yuyy_LedToggle(YUYY_LED3);
  25.         YUYY_DelayMs(1000);
  26.         yuyy_LedToggle(YUYY_LED2|YUYY_LED3);
  27.         if(!YUYY_DHTC12_ReadHT(&dhtc12_dev,&temp,&humi))
  28.         {
  29.             sprintf(out,"T:%03.1f  H:%03.1f%%",temp/10.0,humi/10.0);
  30.             YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,out);
  31.         }
  32.     }
  33. }
运行效果
微信图片_20240511225437.jpg

caigang13 发表于 2024-7-2 08:27 来自手机 | 显示全部楼层
这种小尺寸的OLED用IIC控制还好,屏幕再大点,通信速率上不去了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

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