[活动专区] 【AT-START-F425测评】5、硬件I2C驱动OLED

[复制链接]
1163|1
 楼主| freeelectron 发表于 2022-3-5 17:43 | 显示全部楼层 |阅读模式

1、关于AT32F425的I2C接口 2111262232f31baa59.png

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


2、开发板上I2C的引脚
2231062232f61001fa.png
本文使用I2C1来驱动。

3、通用引脚复用为I2C
133662232f9d5f14a.png

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


4、代码实现
(1)I2C初始化
  1. void I2cInit(void)
  2. {
  3.         gpio_init_type gpio_init_structure;
  4.   
  5.     /* i2c periph clock enable */
  6.     crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);   
  7.     crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  8.    
  9.     /* gpio configuration */  
  10.     gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE6, GPIO_MUX_1);
  11.     gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE7, GPIO_MUX_1);
  12.    
  13.     /* configure i2c pins: scl */
  14.     gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  15.     gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
  16.     gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
  17.     gpio_init_structure.gpio_pull           = GPIO_PULL_UP;  
  18.                                             
  19.     gpio_init_structure.gpio_pins           = GPIO_PINS_6;
  20.     gpio_init(GPIOB, &gpio_init_structure);

  21.     /* configure i2c pins: sda */
  22.     gpio_init_structure.gpio_pins           = GPIO_PINS_7;
  23.     gpio_init(GPIOB, &gpio_init_structure);
  24.    
  25.         /* reset i2c peripheral */
  26.         i2c_reset(I2C1);
  27.        
  28.     /* config i2c */
  29.     i2c_init(I2C1, 0, 0x80E03030); //0x80E06565  0x80E03030
  30.    
  31.     i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, I2C_OWN_ADDRESS7);
  32.   
  33.         /* i2c peripheral enable */   
  34.         i2c_enable(I2C1, TRUE);
  35. }
(2)I2C写
分写命令和写数据。
  1. void OledWriteCmd(uint8_t var)
  2. {
  3.   /* wait for the busy falg to be reset */
  4.   while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) );
  5.   
  6.   /* start transfer */  
  7.   i2c_transmit_set(I2C1, I2C_SLAVE_ADDRESS7, 2, I2C_AUTO_STOP_MODE, I2C_GEN_START_WRITE);
  8.   
  9.   while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  10.   i2c_data_send(I2C1, 0x00);
  11.   
  12.   while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  13.   i2c_data_send(I2C1, var);
  14.   
  15.   while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
  16.   i2c_flag_clear(I2C1, I2C_STOPF_FLAG);
  17. }

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

  24.   while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  25.   i2c_data_send(I2C1, 0x40);
  26.   
  27.   while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
  28.   i2c_data_send(I2C1, var);
  29.   
  30.   while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
  31.   i2c_flag_clear(I2C1, I2C_STOPF_FLAG);

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

  9. //开启Oled显示
  10. void OledDisplayOn(void)
  11. {
  12.   SSD1306_WriteCmd(0X8D);  //SET DCDC命令
  13.   SSD1306_WriteCmd(0X14);  //DCDC ON
  14.   SSD1306_WriteCmd(0XAF);  //DISPLAY ON
  15. }

  16. //关闭Oled显示   
  17. void OledDisplayOff(void)
  18. {
  19.   SSD1306_WriteCmd(0X8D);  //SET DCDC命令
  20.   SSD1306_WriteCmd(0X10);  //DCDC OFF
  21.   SSD1306_WriteCmd(0XAE);  //DISPLAY OFF
  22. }

  23. //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样  
  24. void OledClear(void)  
  25. {  
  26.   uint8_t i,n;       
  27.   
  28.   for(i=0;i<8;i++)  
  29.   {  
  30.     SSD1306_WriteCmd (0xb0+i);    //设置页地址(0~7)
  31.     SSD1306_WriteCmd (0x00);      //设置显示位置—列低地址
  32.     SSD1306_WriteCmd (0x10);      //设置显示位置—列高地址   
  33.     for(n=0;n<128;n++)
  34.       SSD1306_WriteData(0);
  35.   } //更新显示
  36. }

  37. //在指定位置显示一个字符,包括部分字符
  38. //x:0~127,y:0~7
  39. //Char_Size:选择字体 16/12
  40. void OledShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
  41. {             
  42.   uint8_t c=0,i=0;       
  43.   
  44.   c=chr-' ';//得到偏移后的值                       
  45.   if(x>MAX_COLUMN-1)
  46.   {
  47.     x=0;
  48.     y=y+2;
  49.   }
  50.   if(Char_Size ==16)
  51.   {
  52.     OledSetPos(x,y);       
  53.     for(i=0;i<8;i++)
  54.     {
  55.       SSD1306_WriteData(F8X16[c*16+i]);//先写上半部分
  56.     }
  57.    
  58.     OledSetPos(x,y+1);
  59.     for(i=0;i<8;i++)
  60.     {
  61.       SSD1306_WriteData(F8X16[c*16+i+8]);//后写下半部分
  62.     }
  63.   }
  64.   else
  65.   {       
  66.     OledSetPos(x,y);
  67.     for(i=0;i<6;i++)
  68.     {
  69.       SSD1306_WriteData(F6x8[c][i]);
  70.     }
  71.   }
  72. }

  73. //显示一个字符串
  74. void OledShowString(uint8_t x,uint8_t y,char *str,uint8_t Char_Size)
  75. {
  76.   unsigned char j=0;
  77.   
  78.   while (str[j]!='\0')
  79.   {
  80.     OledShowChar(x,y,str[j],Char_Size);
  81.     x+=8;
  82.     if(x>120)
  83.     {
  84.       x=0;
  85.       y+=2;
  86.     }
  87.     j++;//移动一次就是一个page,取值0-7
  88.   }
  89. }

  90. //显示汉字
  91. //由于汉字是16*16大小的,所以最多显示4行汉字
  92. //index:在汉字取模中的索引
  93. void OledShowCN(uint8_t x,uint8_t y,uint8_t index)
  94. {                                  
  95.   uint8_t t;
  96.        
  97.   OledSetPos(x,y);       
  98.   for(t=0;t<16;t++)
  99.   {
  100.     SSD1306_WriteData(Hzk[index][t]);
  101.   }       
  102.   
  103.   OledSetPos(x,y+1);       
  104.   for(t=0;t<16;t++)
  105.   {       
  106.     SSD1306_WriteData(Hzk[index][t+16]);
  107.   }                                       
  108. }
(4)OLED初始化
  1. void OledInit(void)
  2. {
  3.   delay_ms(300);
  4.   delay_ms(300);

  5.   //SSD1306复位之后,默认的是页寻址方式
  6.   
  7.   SSD1306_WriteCmd(0xAE);//--display off
  8.   
  9.   SSD1306_WriteCmd(0x00);//--set low column address
  10.   SSD1306_WriteCmd(0x10);//--set high column address
  11.   SSD1306_WriteCmd(0x40);//--set start line address  
  12.   
  13.   SSD1306_WriteCmd(0xB0);//--set page address
  14.   
  15.   SSD1306_WriteCmd(0x81);// contract control
  16.   SSD1306_WriteCmd(0xFF);//--128   
  17.   SSD1306_WriteCmd(0xA1);//set segment re-map  0 to 127
  18.   SSD1306_WriteCmd(0xA6);//set normal  display  
  19.   SSD1306_WriteCmd(0xA8);//set multiplex ratio(1 to 64)
  20.   SSD1306_WriteCmd(0x3F);//--1/32 duty
  21.   
  22.   SSD1306_WriteCmd(0xC8);//Com scan direction
  23.   SSD1306_WriteCmd(0xD3);//set display offset
  24.   SSD1306_WriteCmd(0x00);//no offset
  25.        
  26.   SSD1306_WriteCmd(0xD5);//set display clock divide ratio/oscillator frequency  
  27.   SSD1306_WriteCmd(0x80);//
  28.        
  29.   SSD1306_WriteCmd(0xD8);//set area color mode off
  30.   SSD1306_WriteCmd(0x05);//
  31.        
  32.   SSD1306_WriteCmd(0xD9);//Set Pre-Charge Period
  33.   SSD1306_WriteCmd(0xF1);//
  34.        
  35.   SSD1306_WriteCmd(0xDA);//set com pin  hardware configuartion
  36.   SSD1306_WriteCmd(0x12);//
  37.        
  38.   SSD1306_WriteCmd(0xDB);//set Vcomh
  39.   SSD1306_WriteCmd(0x30);//0x20,0.77xVcc
  40.        
  41.   SSD1306_WriteCmd(0x8D);//set charge pump enable
  42.   SSD1306_WriteCmd(0x14);//
  43.        
  44.   SSD1306_WriteCmd(0xAF);//--turn on Oled panel
  45. }
(5)显示测试
  1. void OledDisplayTest(void)
  2. {
  3.         I2cInit();
  4.         OledInit();
  5.        
  6.         OledClear();

  7.         OledShowString(48,0,(char *)("21ic"),16);
  8.        
  9.         OledShowCN(40,2,4);
  10.         OledShowCN(56,2,5);
  11.         OledShowCN(72,2,6);
  12.        
  13.         OledShowString(40,4,(char *)("2022"),16);

  14.         OledShowCN(24,6,0);
  15.         OledShowCN(40,6,1);
  16.         OledShowCN(56,6,2);
  17.         OledShowCN(72,6,3);
  18. }
5、现象
31660622330b1a82d3.png








airhejoin 发表于 2022-11-1 13:53 | 显示全部楼层
兄弟 代码能不能分享一下 我的代码写十几二十个数据 就会卡住
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

66

主题

786

帖子

11

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