[AT32L021] 【AT-START-L021测评】+i2c驱动OLED显示屏

[复制链接]
 楼主| tlled 发表于 2024-11-28 00:25 | 显示全部楼层 |阅读模式
测试使用I2C硬件方式驱动OLED显示屏。

一、硬件接口

驱动OLED显示屏,使用i2c1,使用到PB6和PB7,在软件中配置端口。
001.png

二、程序部分

2.1、oled.c
  1. #include "at32l021.h"
  2. #include "oled/oled.h"
  3. #include "oled/codetab.h"
  4. #include "delay/delay.h"
  5. #include "i2c/i2c.h"
  6. #include "i2c_application.h"

  7. void I2C_WriteByte(uint8_t addr, uint8_t dat)
  8. {
  9.   uint8_t temp[2];
  10.   temp[0] = addr;
  11.         temp[1] = dat;
  12.         i2c_senddat(OLED_ADDRESS, temp, 2);
  13. }


  14. void WriteCmd(unsigned char I2C_Command)
  15. {
  16.     I2C_WriteByte(0x00, I2C_Command);
  17. }

  18. void WriteDat(unsigned char I2C_Data)
  19. {
  20.     I2C_WriteByte(0x40, I2C_Data);
  21. }

  22. void OLED_WrCmd(unsigned char IIC_Command)
  23. {
  24.         WriteCmd(IIC_Command);
  25. }

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

  58. void OLED_SetPos(unsigned char x, unsigned char y)
  59. {
  60.         WriteCmd(0xb0+y);
  61.         WriteCmd(((x&0xf0)>>4)|0x10);
  62.         WriteCmd((x&0x0f)|0x01);
  63. }

  64. void OLED_Fill(unsigned char fill_Data)//全屏填充
  65. {
  66.         unsigned char m,n;
  67.         for(m=0;m<8;m++)
  68.         {
  69.                 WriteCmd(0xb0+m);                //page0-page1
  70.                 WriteCmd(0x00);                //low column start address
  71.                 WriteCmd(0x10);                //high column start address
  72.                 for(n=0;n<128;n++)
  73.                         {
  74.                                 WriteDat(fill_Data);
  75.                         }
  76.         }
  77. }

  78. void OLED_CLS(void)//清屏
  79. {
  80.         OLED_Fill(0xff);
  81. }

  82. void OLED_ON(void)
  83. {
  84.         WriteCmd(0X8D);  //设置电荷泵
  85.         WriteCmd(0X14);  //开启电荷泵
  86.         WriteCmd(0XAF);  //OLED唤醒
  87. }

  88. void OLED_OFF(void)
  89. {
  90.         WriteCmd(0X8D);  //设置电荷泵
  91.         WriteCmd(0X10);  //关闭电荷泵
  92.         WriteCmd(0XAE);  //OLED休眠
  93. }

  94. void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
  95. {
  96.         unsigned char c = 0,i = 0,j = 0;
  97.         switch(TextSize)
  98.         {
  99.                 case 1:
  100.                 {
  101.                         while(ch[j] != '\0')
  102.                         {
  103.                                 c = ch[j] - 32;
  104.                                 if(x > 126)
  105.                                 {
  106.                                         x = 0;
  107.                                         y++;
  108.                                 }
  109.                                 OLED_SetPos(x,y);
  110.                                 for(i=0;i<6;i++)
  111.                                         WriteDat(F6x8[c][i]);
  112.                                 x += 6;
  113.                                 j++;
  114.                         }
  115.                 }break;
  116.                 case 2:
  117.                 {
  118.                         while(ch[j] != '\0')
  119.                         {
  120.                                 c = ch[j] - 32;
  121.                                 if(x > 120)
  122.                                 {
  123.                                         x = 0;
  124.                                         y++;
  125.                                 }
  126.                                 OLED_SetPos(x,y);
  127.                                 for(i=0;i<8;i++)
  128.                                         WriteDat(F8X16[c*16+i]);
  129.                                 OLED_SetPos(x,y+1);
  130.                                 for(i=0;i<8;i++)
  131.                                         WriteDat(F8X16[c*16+i+8]);
  132.                                 x += 8;
  133.                                 j++;
  134.                         }
  135.                 }break;
  136.         }
  137. }

  138. void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
  139. {
  140.         unsigned char wm=0;
  141.         unsigned int  adder=32*N;
  142.         OLED_SetPos(x , y);
  143.         for(wm = 0;wm < 16;wm++)
  144.         {
  145.                 WriteDat(F16x16[adder]);
  146.                 adder += 1;
  147.         }
  148.         OLED_SetPos(x,y + 1);
  149.         for(wm = 0;wm < 16;wm++)
  150.         {
  151.                 WriteDat(F16x16[adder]);
  152.                 adder += 1;
  153.         }
  154. }

  155. void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
  156. {
  157.         unsigned int j=0;
  158.         unsigned char x,y;

  159.   if(y1%8==0)
  160.                 y = y1/8;
  161.   else
  162.                 y = y1/8 + 1;
  163.         for(y=y0;y<y1;y++)
  164.         {
  165.                 OLED_SetPos(x0,y);
  166.     for(x=x0;x<x1;x++)
  167.                 {
  168.                         WriteDat(BMP[j++]);
  169.                 }
  170.         }
  171. }

  172. void oled_test(void)
  173. {
  174.         OLED_Init();
  175.         OLED_Fill(0x00);
  176.         OLED_ShowStr(0,0,"AT32L021 BOARD",2);
  177.         OLED_ShowStr(0,2,"I2C OLED TEST",2);       
  178. }


2.2、i2c.c
  1. #include "at32l021.h"
  2. #include "i2c/i2c.h"
  3. #include "i2c_application.h"

  4. i2c_handle_type hi2cx;

  5. /**
  6.   * [url=home.php?mod=space&uid=247401]@brief[/url]  initializes peripherals used by the i2c.
  7.   * @param  none
  8.   * @retval none
  9.   */
  10. void i2c_lowlevel_init(i2c_handle_type* hi2c)
  11. {
  12.   gpio_init_type gpio_init_structure;

  13.   if(hi2c->i2cx == I2Cx_PORT)
  14.   {
  15.     /* i2c periph clock enable */
  16.     crm_periph_clock_enable(I2Cx_CLK, TRUE);
  17.     crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
  18.     crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);

  19.     /* gpio configuration */
  20.     gpio_pin_mux_config(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_GPIO_PinsSource, I2Cx_SCL_GPIO_MUX);

  21.     gpio_pin_mux_config(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_GPIO_PinsSource, I2Cx_SDA_GPIO_MUX);

  22.     /* configure i2c pins: scl */
  23.     gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  24.     gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
  25.     gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
  26.     gpio_init_structure.gpio_pull           = GPIO_PULL_NONE;

  27.     gpio_init_structure.gpio_pins           = I2Cx_SCL_GPIO_PIN;
  28.     gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_init_structure);

  29.     /* configure i2c pins: sda */
  30.     gpio_init_structure.gpio_pins           = I2Cx_SDA_GPIO_PIN;
  31.     gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_init_structure);

  32.     /* config i2c */
  33.     i2c_init(hi2c->i2cx, 0x0F, I2Cx_CLKCTRL);

  34.     i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2Cx_ADDRESS);
  35.   }
  36. }

  37. void init_i2c(void){
  38.         hi2cx.i2cx = I2Cx_PORT;
  39.         i2c_config(&hi2cx);
  40. }

  41. void i2c_senddat(uint16_t address, uint8_t* pdata, uint16_t size)
  42. {
  43.         i2c_master_transmit(&hi2cx, address, pdata, size, I2C_TIMEOUT);
  44.        
  45. }



2.3、main.c
  1. #include "at32l021_clock.h"
  2. #include "led/led.h"
  3. #include "delay/delay.h"
  4. #include "i2c/i2c.h"
  5. #include "oled/oled.h"

  6. int main(void)
  7. {
  8.   system_clock_config();
  9.         delay_init();
  10.         init_led();
  11.         init_i2c();
  12.         OLED_Init();
  13.         oled_test();
  14.   while(1)
  15.   {
  16.     led2_tog();
  17.     delay_ms(200);
  18.     led3_tog();
  19.     delay_ms(200);
  20.     led4_tog();
  21.     delay_ms(200);
  22.   }
  23. }


三、程序运行

下载程序后,OLED显示屏显示内容
oled.jpg
sanfuzi 发表于 2024-12-3 08:05 | 显示全部楼层
OLED的初始化过程涉及一系列I2C命令的发送,例如设置显示模式、对比度、显示方向等。
sanfuzi 发表于 2024-12-6 19:50 | 显示全部楼层
I2C接口的OLED显示屏通常带有控制器(如SSD1306),这使得显示屏的控制变得简单,只需发送相应的指令和数据即可。
zerorobert 发表于 2024-12-6 21:23 | 显示全部楼层
使用I2C驱动OLED显示屏可以提供较高的数据传输速率,满足大多数应用场景的需求。同时,AT-START-L021的高主频和强大的处理能力可以确保流畅的显示效果。
burgessmaggie 发表于 2024-12-7 00:24 | 显示全部楼层
硬件I2C相比软件I2C通常具有更高的通信速度和更好的稳定性,这有助于提升OLED显示屏的刷新率和显示效果。
fengm 发表于 2024-12-7 03:25 | 显示全部楼层
OLED显示屏本身也具有一定的成本,但在许多应用中,其高对比度、低功耗和轻薄的特点使得它成为了一个非常有价值的选择。
sheflynn 发表于 2024-12-7 06:29 | 显示全部楼层
I2C协议简单易懂,使得OLED显示屏的集成变得相对容易。
chenci2013 发表于 2024-12-9 10:08 | 显示全部楼层
I2C接口本身具有较低的功耗特性,适合电池供电的应用场景。AT-START-L021也具备多种低功耗模式,可以进一步降低系统功耗。
mattlincoln 发表于 2024-12-9 13:17 | 显示全部楼层
使用I2C硬件方式驱动OLED显示屏是一种常见的做法,因为它可以减少微控制器的引脚使用,同时提供较高的通信效率和稳定性。
10299823 发表于 2024-12-9 16:22 | 显示全部楼层
OLED显示屏具有许多优点,但它们的成本可能高于传统的LCD显示屏,这需要在设计时考虑成本效益。
gygp 发表于 2024-12-10 12:39 | 显示全部楼层
可以快速实现OLED显示屏的驱动和显示功能。
qiufengsd 发表于 2024-12-10 14:01 | 显示全部楼层
OLED 显示屏在硬件层面展现出诸多优势。
olivem55arlowe 发表于 2024-12-10 15:02 | 显示全部楼层
AT-START-L021开发板上配有Arduino Uno R3扩展接口?
 楼主| tlled 发表于 2024-12-10 15:40 | 显示全部楼层
olivem55arlowe 发表于 2024-12-10 15:02
AT-START-L021开发板上配有Arduino Uno R3扩展接口?

有的
benjaminka 发表于 2024-12-10 17:05 | 显示全部楼层
OLED显示屏具有很高的对比度,可以提供清晰的显示效果,适合在各种光照条件下使用。
houjiakai 发表于 2024-12-10 18:01 | 显示全部楼层
硬件I2C需要额外的硬件资源,如I2C通信芯片或FPGA等,这可能会增加一些成本。然而,对于需要高速、稳定通信的应用来说,这些成本可能是值得的。
louliana 发表于 2024-12-10 18:58 | 显示全部楼层
OLED显示屏相比传统LCD显示屏具有更低的功耗,这使得整个系统更加节能。
jtracy3 发表于 2024-12-11 16:07 | 显示全部楼层
OLED显示屏的刷新率和分辨率可能会影响系统的性能,特别是在处理复杂图形或动画时。
primojones 发表于 2024-12-11 22:20 | 显示全部楼层
理解和使用这些库函数可能需要一定的学习成本。
bestwell 发表于 2024-12-11 22:47 | 显示全部楼层
使用DMA(直接内存访问)等高级功能可以进一步提升通信效率和显示效果,这在一些高级应用中可能是一个重要的考虑因素。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

132

主题

701

帖子

7

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