[活动] 【APM32F411V开发板测评】+IIC驱动OLED屏幕

[复制链接]
 楼主| 小叶三千 发表于 2024-6-6 16:40 | 显示全部楼层 |阅读模式
    收到极海的开发板,首先要驱动一下自己正在做的一个项目的外设,OLED屏幕显示!

   1、考虑到模块移植的通用性,所以选择了模拟IIC驱动
         GPIO初始化SDA和SCL引脚
  1. void OLED_GPIO_Init(void)
  2. {
  3.         GPIO_Config_T  configStruct;

  4.         RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOD);

  5.         GPIO_ConfigStructInit(&configStruct);
  6.         configStruct.pin = SDA_PIN | SCL_PIN;
  7.         configStruct.mode = GPIO_MODE_OUT;
  8.         configStruct.speed = GPIO_SPEED_50MHz;

  9.         GPIO_Config(SDA_PORT, &configStruct);


  10.         GPIO_SetBit(SDA_PORT, SDA_PIN);
  11.         GPIO_SetBit(SCL_PORT, SCL_PIN);
  12. }

     设置输入和输出方向
  1. void SDA2_OUT()
  2. {
  3.         GPIO_Config_T  configStruct;


  4.         GPIO_ConfigStructInit(&configStruct);
  5.         configStruct.pin = SDA_PIN;
  6.         configStruct.mode = GPIO_MODE_OUT;
  7.         configStruct.speed = GPIO_SPEED_50MHz;

  8.         GPIO_Config(SDA_PORT, &configStruct);
  9. }

  10. void SDA2_IN()
  11. {
  12.         GPIO_Config_T  configStruct;


  13.         GPIO_ConfigStructInit(&configStruct);
  14.         configStruct.pin = SDA_PIN;
  15.         configStruct.mode = GPIO_MODE_IN;
  16.          configStruct.pupd  = GPIO_PUPD_UP;

  17.         GPIO_Config(SDA_PORT, &configStruct);
  18. }
   接着就是IIC的开始、结束、ACK、写入一个字节
  1. //开始信号
  2. void IIC2_Start(void)
  3. {
  4.     SDA2_OUT();
  5.     GPIO_SetBit(SDA_PORT, SDA_PIN);
  6.     GPIO_SetBit(SCL_PORT, SCL_PIN);
  7.     Delay_us(2);
  8.     GPIO_ResetBit(SDA_PORT, SDA_PIN);
  9.     Delay_us(2);
  10.     GPIO_ResetBit(SCL_PORT, SCL_PIN);
  11.     Delay_us(2);
  12. }

  13. void IIC2_Stop(void)
  14. {
  15.     GPIO_SetBit(SCL_PORT, SCL_PIN);
  16.     GPIO_ResetBit(SDA_PORT, SDA_PIN);
  17.     Delay_us(2);
  18.     GPIO_SetBit(SDA_PORT, SDA_PIN);
  19.     Delay_us(2);
  20. }


  21. /*
  22. *   返回1--应答出错
  23. *   放回0--应答正确
  24. */
  25. u8 IIC_Wait_Ask(void)
  26. {
  27.     int count=0;
  28.     SDA2_IN();
  29.     GPIO_SetBit(SCL_PORT, SCL_PIN);
  30.     Delay_us(20);
  31.     while(GPIO_ReadInputBit(SDA_PORT, SDA_PIN))
  32.     {
  33.         count++;
  34.         if(count>250)
  35.         {
  36.             IIC2_Stop();
  37.             return 1;
  38.         }   
  39.     }
  40.     GPIO_ResetBit(SCL_PORT, SCL_PIN);
  41.     Delay_us(2);
  42.     return 0;
  43. }

  44. //写一个字节
  45. void IIC_WriteByte(u8 data)
  46. {
  47.     u8 i;
  48.     SDA2_OUT();
  49.     for(i=0;i<8;i++)
  50.     {
  51.         GPIO_ResetBit(SCL_PORT, SCL_PIN);
  52.         Delay_us(2);
  53.         if(data & 0x80)     //MSB,从高位开始一位一位传输
  54.             GPIO_SetBit(SDA_PORT, SDA_PIN);
  55.         else
  56.             GPIO_ResetBit(SDA_PORT, SDA_PIN);
  57.         GPIO_SetBit(SCL_PORT, SCL_PIN);
  58.         Delay_us(2);
  59.         GPIO_ResetBit(SCL_PORT, SCL_PIN);
  60.         data<<=1;

  61.     }
  62. }
   然后开始OLED的驱动
  1. void WriteCmd(u8 command)
  2. {
  3.     IIC2_Start();
  4.     IIC_WriteByte(0x78);//OLED地址
  5.     IIC_Wait_Ask();
  6.     IIC_WriteByte(0x00);//寄存器地址
  7.     IIC_Wait_Ask();
  8.     IIC_WriteByte(command);
  9.     IIC_Wait_Ask();
  10.     IIC2_Stop();
  11. }


  12. void WriteDat(u8 data)
  13. {
  14.     IIC2_Start();
  15.     IIC_WriteByte(0x78);//OLED地址
  16.     IIC_Wait_Ask();
  17.     IIC_WriteByte(0x40);//寄存器地址
  18.     IIC_Wait_Ask();
  19.     IIC_WriteByte(data);
  20.     IIC_Wait_Ask();
  21.     IIC2_Stop();
  22. }

  23. void OLED_Init(void)
  24. {               
  25.        
  26.     Delay_ms(100); //这里的延时很重要
  27.         WriteCmd(0xAE); //display off
  28.     WriteCmd(0x20); //Set Memory Addressing Mode   
  29.     WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
  30.     WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
  31.     WriteCmd(0xc8); //Set COM Output Scan Direction
  32.     WriteCmd(0x00); //---set low column address
  33.     WriteCmd(0x10); //---set high column address
  34.     WriteCmd(0x40); //--set start line address
  35.     WriteCmd(0x81); //--set contrast control register
  36.     WriteCmd(0xff); //???? 0x00~0xff
  37.     WriteCmd(0xa1); //--set segment re-map 0 to 127
  38.     WriteCmd(0xa6); //--set normal display
  39.     WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
  40.     WriteCmd(0x3F); //
  41.     WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
  42.     WriteCmd(0xd3); //-set display offset
  43.     WriteCmd(0x00); //-not offset
  44.     WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
  45.     WriteCmd(0xf0); //--set divide ratio
  46.     WriteCmd(0xd9); //--set pre-charge period
  47.     WriteCmd(0x22); //
  48.     WriteCmd(0xda); //--set com pins hardware configuration
  49.     WriteCmd(0x12);
  50.     WriteCmd(0xdb); //--set vcomh
  51.     WriteCmd(0x20); //0x20,0.77xVcc
  52.     WriteCmd(0x8d); //--set DC-DC enable
  53.     WriteCmd(0x14); //
  54.     WriteCmd(0xaf); //--turn on oled panel
  55.                 OLED_CLS();
  56. }


  57. /**
  58.   * [url=home.php?mod=space&uid=247401]@brief[/url]  OLED_ON,将OLED从休眠中唤醒
  59.   * @param  无
  60.     * @retval 无
  61.   */
  62. void OLED_ON(void)
  63. {
  64.     WriteCmd(0X8D);  //设置电荷泵
  65.     WriteCmd(0X14);  //开启电荷泵
  66.     WriteCmd(0XAF);  //OLED唤醒
  67. }


  68. /**
  69.   * @brief  OLED_SetPos,设置光标
  70.   * @param  x,光标x位置
  71.     *                   y,光标y位置
  72.   * @retval 无
  73.   */
  74. void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
  75. {
  76.     WriteCmd(0xb0+y);
  77.     WriteCmd(((x&0xf0)>>4)|0x10);
  78.     WriteCmd((x&0x0f)|0x01);
  79. }

  80. /**
  81.   * @brief  OLED_Fill,填充整个屏幕
  82.   * @param  fill_Data:要填充的数据
  83.     * @retval 无
  84.   */
  85. void OLED_Fill(unsigned char fill_Data)//全屏填充
  86. {
  87.     unsigned char m,n;
  88.     for(m=0;m<8;m++)
  89.     {
  90.         WriteCmd(0xb0+m);       //page0-page1
  91.         WriteCmd(0x00);     //low column start address
  92.         WriteCmd(0x10);     //high column start address
  93.         for(n=0;n<128;n++)
  94.             {
  95.                 WriteDat(fill_Data);
  96.             }
  97.     }
  98. }


  99. void OLED_CLS(void)//清屏
  100. {
  101.     OLED_Fill(0x00);
  102. }




  103. void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
  104. {
  105.     unsigned char c = 0,i = 0,j = 0;
  106.     switch(TextSize)
  107.     {
  108.         case 1:
  109.         {
  110.             while(ch[j] != '\0')
  111.             {
  112.                 c = ch[j] - 32;
  113.                 if(x > 126)
  114.                 {
  115.                     x = 0;
  116.                     y++;
  117.                 }
  118.                 OLED_SetPos(x,y);
  119.                 for(i=0;i<6;i++)
  120.                     WriteDat(F6x8[c][i]);
  121.                 x += 6;
  122.                 j++;
  123.             }
  124.         }break;
  125.         case 2:
  126.         {
  127.             while(ch[j] != '\0')
  128.             {
  129.                 c = ch[j] - 32;
  130.                 if(x > 120)
  131.                 {
  132.                     x = 0;
  133.                     y++;
  134.                 }
  135.                 OLED_SetPos(x,y);
  136.                 for(i=0;i<8;i++)
  137.                     WriteDat(F8X16[c*16+i]);
  138.                 OLED_SetPos(x,y+1);
  139.                 for(i=0;i<8;i++)
  140.                     WriteDat(F8X16[c*16+i+8]);
  141.                 x += 8;
  142.                 j++;
  143.             }
  144.         }break;
  145.     }
  146. }
   OK,到这里驱动就算结束了,然后我们再main里写要显示的内容
  1. unsigned char name8[] = "Geehy";
  2. unsigned char name7[] = "BBS: 21ic.com";
  3. unsigned char name6[] = "Mode: IIC\0";
  4. unsigned char name5[] = "Drv: OLED\0";

  5. int main(void)
  6.         {
  7.         /* Set system interrupt priority grouping */
  8.         NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_2);

  9.         /* Init delay function */
  10.         Delay_Init();

  11.         /* Init LED */
  12.         APM_LEDInit(LED2);
  13.         APM_LEDInit(LED3);

  14.         OLED_Init();
  15.         OLED_CLS();
  16.                
  17.         OLED_ShowStr(40, 0, name8, 2);

  18.         OLED_ShowStr(0, 2, name7, 2);

  19.         OLED_ShowStr(0, 4, name6, 2);

  20.         OLED_ShowStr(0, 6, name5, 2);

  21.         while(1)
  22.         {
  23.                 Delay_ms(500);
  24.                 GPIOE->ODATA ^= GPIO_PIN_5;
  25.                 GPIOE->ODATA ^= GPIO_PIN_6;
  26.         }
  27. }


     最后看效果图




32323微信图片_20240606163941.jpg
weifeng90 发表于 2024-6-6 19:04 来自手机 | 显示全部楼层
IIC通信速率有限,屏幕刷新有点慢。
星辰大海不退缩 发表于 2024-6-22 21:38 | 显示全部楼层
楼主可以更换一个SPI通信的屏幕
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:清智科技嵌入式工程师
简介:单片机嵌入式底层开发,汽车电子

49

主题

515

帖子

18

粉丝
认证:清智科技嵌入式工程师
简介:单片机嵌入式底层开发,汽车电子

49

主题

515

帖子

18

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