打印
[活动专区]

【AT-START-F425测评】5、硬件I2C驱动OLED

[复制链接]
882|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

1、关于AT32F425的I2C接口

可以看出有两路I2C,分别是I2C1,I2C2。


2、开发板上I2C的引脚

本文使用I2C1来驱动。

3、通用引脚复用为I2C

可以看出,是复用功能1。


4、代码实现
(1)I2C初始化
void I2cInit(void)
{
        gpio_init_type gpio_init_structure;
  
    /* i2c periph clock enable */
    crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);   
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
   
    /* gpio configuration */  
    gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_1);
    gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_1);
   
    /* configure i2c pins: scl */
    gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
    gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_structure.gpio_pull           = GPIO_PULL_UP;  
                                            
    gpio_init_structure.gpio_pins           = GPIO_PINS_6;
    gpio_init(GPIOB, &gpio_init_structure);

    /* configure i2c pins: sda */
    gpio_init_structure.gpio_pins           = GPIO_PINS_7;
    gpio_init(GPIOB, &gpio_init_structure);
   
        /* reset i2c peripheral */
        i2c_reset(I2C1);
       
    /* config i2c */
    i2c_init(I2C1, 0, 0x80E03030); //0x80E06565  0x80E03030
   
    i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, I2C_OWN_ADDRESS7);
  
        /* i2c peripheral enable */   
        i2c_enable(I2C1, TRUE);
}
(2)I2C写
分写命令和写数据。
void OledWriteCmd(uint8_t var)
{
  /* wait for the busy falg to be reset */
  while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) );
  
  /* start transfer */  
  i2c_transmit_set(I2C1, I2C_SLAVE_ADDRESS7, 2, I2C_AUTO_STOP_MODE, I2C_GEN_START_WRITE);
  
  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, 0x00);
  
  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, var);
  
  while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
  i2c_flag_clear(I2C1, I2C_STOPF_FLAG);
}

void OledWriteData(uint8_t var)
{
  /* wait for the busy falg to be reset */
  while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) );
  /* start transfer */
  i2c_transmit_set(I2C1, I2C_SLAVE_ADDRESS7, 2, I2C_AUTO_STOP_MODE, I2C_GEN_START_WRITE);

  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, 0x40);
  
  while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  i2c_data_send(I2C1, var);
  
  while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
  i2c_flag_clear(I2C1, I2C_STOPF_FLAG);

}
(3)OLED相关驱动
//坐标设置:也就是在哪里显示
void OledSetPos(uint8_t x, uint8_t y)
{
  //以下3个寄存器只在页寻址的模式下有效       
  SSD1306_WriteCmd(0xb0+y);             //页地址设置     0xb0~0xb7
  SSD1306_WriteCmd(((x&0xf0)>>4)|0x10); //列高位地址设置
  SSD1306_WriteCmd((x&0x0f));           //列低位地址设置
}

//开启Oled显示
void OledDisplayOn(void)
{
  SSD1306_WriteCmd(0X8D);  //SET DCDC命令
  SSD1306_WriteCmd(0X14);  //DCDC ON
  SSD1306_WriteCmd(0XAF);  //DISPLAY ON
}

//关闭Oled显示   
void OledDisplayOff(void)
{
  SSD1306_WriteCmd(0X8D);  //SET DCDC命令
  SSD1306_WriteCmd(0X10);  //DCDC OFF
  SSD1306_WriteCmd(0XAE);  //DISPLAY OFF
}

//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样  
void OledClear(void)  
{  
  uint8_t i,n;       
  
  for(i=0;i<8;i++)  
  {  
    SSD1306_WriteCmd (0xb0+i);    //设置页地址(0~7)
    SSD1306_WriteCmd (0x00);      //设置显示位置—列低地址
    SSD1306_WriteCmd (0x10);      //设置显示位置—列高地址   
    for(n=0;n<128;n++)
      SSD1306_WriteData(0);
  } //更新显示
}

//在指定位置显示一个字符,包括部分字符
//x:0~127,y:0~7
//Char_Size:选择字体 16/12
void OledShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{             
  uint8_t c=0,i=0;       
  
  c=chr-' ';//得到偏移后的值                       
  if(x>MAX_COLUMN-1)
  {
    x=0;
    y=y+2;
  }
  if(Char_Size ==16)
  {
    OledSetPos(x,y);       
    for(i=0;i<8;i++)
    {
      SSD1306_WriteData(F8X16[c*16+i]);//先写上半部分
    }
   
    OledSetPos(x,y+1);
    for(i=0;i<8;i++)
    {
      SSD1306_WriteData(F8X16[c*16+i+8]);//后写下半部分
    }
  }
  else
  {       
    OledSetPos(x,y);
    for(i=0;i<6;i++)
    {
      SSD1306_WriteData(F6x8[c][i]);
    }
  }
}

//显示一个字符串
void OledShowString(uint8_t x,uint8_t y,char *str,uint8_t Char_Size)
{
  unsigned char j=0;
  
  while (str[j]!='\0')
  {
    OledShowChar(x,y,str[j],Char_Size);
    x+=8;
    if(x>120)
    {
      x=0;
      y+=2;
    }
    j++;//移动一次就是一个page,取值0-7
  }
}

//显示汉字
//由于汉字是16*16大小的,所以最多显示4行汉字
//index:在汉字取模中的索引
void OledShowCN(uint8_t x,uint8_t y,uint8_t index)
{                                  
  uint8_t t;
       
  OledSetPos(x,y);       
  for(t=0;t<16;t++)
  {
    SSD1306_WriteData(Hzk[index][t]);
  }       
  
  OledSetPos(x,y+1);       
  for(t=0;t<16;t++)
  {       
    SSD1306_WriteData(Hzk[index][t+16]);
  }                                       
}
(4)OLED初始化
void OledInit(void)
{
  delay_ms(300);
  delay_ms(300);

  //SSD1306复位之后,默认的是页寻址方式
  
  SSD1306_WriteCmd(0xAE);//--display off
  
  SSD1306_WriteCmd(0x00);//--set low column address
  SSD1306_WriteCmd(0x10);//--set high column address
  SSD1306_WriteCmd(0x40);//--set start line address  
  
  SSD1306_WriteCmd(0xB0);//--set page address
  
  SSD1306_WriteCmd(0x81);// contract control
  SSD1306_WriteCmd(0xFF);//--128   
  SSD1306_WriteCmd(0xA1);//set segment re-map  0 to 127
  SSD1306_WriteCmd(0xA6);//set normal  display  
  SSD1306_WriteCmd(0xA8);//set multiplex ratio(1 to 64)
  SSD1306_WriteCmd(0x3F);//--1/32 duty
  
  SSD1306_WriteCmd(0xC8);//Com scan direction
  SSD1306_WriteCmd(0xD3);//set display offset
  SSD1306_WriteCmd(0x00);//no offset
       
  SSD1306_WriteCmd(0xD5);//set display clock divide ratio/oscillator frequency  
  SSD1306_WriteCmd(0x80);//
       
  SSD1306_WriteCmd(0xD8);//set area color mode off
  SSD1306_WriteCmd(0x05);//
       
  SSD1306_WriteCmd(0xD9);//Set Pre-Charge Period
  SSD1306_WriteCmd(0xF1);//
       
  SSD1306_WriteCmd(0xDA);//set com pin  hardware configuartion
  SSD1306_WriteCmd(0x12);//
       
  SSD1306_WriteCmd(0xDB);//set Vcomh
  SSD1306_WriteCmd(0x30);//0x20,0.77xVcc
       
  SSD1306_WriteCmd(0x8D);//set charge pump enable
  SSD1306_WriteCmd(0x14);//
       
  SSD1306_WriteCmd(0xAF);//--turn on Oled panel
}
(5)显示测试
void OledDisplayTest(void)
{
        I2cInit();
        OledInit();
       
        OledClear();

        OledShowString(48,0,(char *)("21ic"),16);
       
        OledShowCN(40,2,4);
        OledShowCN(56,2,5);
        OledShowCN(72,2,6);
       
        OledShowString(40,4,(char *)("2022"),16);

        OledShowCN(24,6,0);
        OledShowCN(40,6,1);
        OledShowCN(56,6,2);
        OledShowCN(72,6,3);
}
5、现象









使用特权

评论回复
沙发
airhejoin| | 2022-11-1 13:53 | 只看该作者
兄弟 代码能不能分享一下 我的代码写十几二十个数据 就会卡住

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:stm32/LoRa物联网:304350312

65

主题

785

帖子

11

粉丝