[开发板] [开发板] CW32L0开发板学习记录五:移植调试IIC

[复制链接]
995|6
 楼主| 聪聪哥哥 发表于 2024-12-30 15:04 | 显示全部楼层 |阅读模式
本帖最后由 聪聪哥哥 于 2024-12-30 15:12 编辑

简介:今天和大家分享一下使用CW32L010开发板,使用模拟IIC驱动OLED的显示;
一:OLED基本知识的分享:
OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。因为具备轻薄、省电等特性,因此从 2003 年开始,这种显示设备在 MP3 播放器上得到了广泛应用,而对于同属数码类产品的 DC 与手机,此前只是在一些展会上展示过采用 OLED 屏幕的工程样品。自 2007 年后,寿命得 到很大提高,具备了许多 LCD 不可比拟的优势。
实物图片:
图片8.png
二:汉字显示的基本方式:
需要我们自己制作字库
图片15.png
根据根据自己的扫描方式,设置不同的驱动方式:
图片10.png
三:软件部分:
  1. /*引脚配置*/
  2. #define OLED_W_SCL(x)                GPIO_WritePin(CW_GPIOA, GPIO_PIN_3, (GPIO_PinState)(x))
  3. #define OLED_W_SDA(x)                GPIO_WritePin(CW_GPIOA, GPIO_PIN_4, (GPIO_PinState)(x))
  4. #define ReadSDA   GPIO_ReadPin(CW_GPIOA, GPIO_PIN_4)   //读SDA电平
  5. #define ReadSCL   GPIO_ReadPin(CW_GPIOA, GPIO_PIN_3)   //读SCL电平
  6. /*引脚初始化*/
  7. void OLED_I2C_Init(void)
  8. {
  9. __SYSCTRL_GPIOA_CLK_ENABLE();
  10.        
  11.         GPIO_InitTypeDef GPIO_InitStruct;
  12.         GPIO_InitStruct.IT=GPIO_IT_NONE;
  13.         GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_OD;
  14.         GPIO_InitStruct.Pins=GPIO_PIN_3 | GPIO_PIN_4;
  15. ////        GPIO_InitStruct.Speed=GPIO_SPEED_LOW;
  16.         GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
  17.         GPIO_WritePin(CW_GPIOA,GPIO_PIN_3 | GPIO_PIN_4,GPIO_Pin_SET);       
  18.         OLED_W_SCL(1);
  19.         OLED_W_SDA(1);
  20. }

  21. /**
  22.   * [url=home.php?mod=space&uid=247401]@brief[/url]  I2C开始
  23.   * @param  无
  24.   * @retval 无
  25.   */
  26. uint8_t OLED_I2C_Start(void)
  27. {
  28.         OLED_W_SDA(1);
  29.         OLED_W_SCL(1);
  30.         OLED_W_SDA(0);
  31.         OLED_W_SCL(0);
  32. }

  33. /**
  34.   * @brief  I2C停止
  35.   * @param  无
  36.   * @retval 无
  37.   */
  38. void OLED_I2C_Stop(void)
  39. {
  40.         OLED_W_SDA(0);
  41.         OLED_W_SCL(0);
  42.         OLED_W_SCL(1);
  43.         OLED_W_SDA(1);
  44. }

  45. /**
  46.   * @brief  I2C发送一个字节
  47.   * @param  Byte 要发送的一个字节
  48.   * @retval 无
  49.   */
  50. void OLED_I2C_SendByte(uint8_t Byte)
  51. {
  52.         uint8_t i;
  53.         for (i = 0; i < 8; i++)
  54.         {
  55.                 if(Byte & (0x80 >> i)) OLED_W_SDA(1);
  56.                 else OLED_W_SDA(0);
  57.                 OLED_W_SCL(1);
  58.                 OLED_W_SCL(0);
  59.         }
  60.         OLED_W_SCL(1);        //额外的一个时钟,不处理应答信号
  61.         OLED_W_SCL(0);
  62. }

  63. /**
  64.   * @brief  OLED写命令
  65.   * @param  Command 要写入的命令
  66.   * @retval 无
  67.   */
  68. void OLED_WriteCommand(uint8_t Command)
  69. {
  70.         OLED_I2C_Start();
  71.         OLED_I2C_SendByte(0x78);                //从机地址
  72.         OLED_I2C_SendByte(0x00);                //写命令
  73.         OLED_I2C_SendByte(Command);
  74.         OLED_I2C_Stop();
  75. }
  1. /**
  2.   * @brief  OLED写数据
  3.   * @param  Data 要写入的数据
  4.   * @retval 无
  5.   */
  6. void OLED_WriteData(uint8_t Data)
  7. {
  8.         OLED_I2C_Start();
  9.         OLED_I2C_SendByte(0x78);                //从机地址
  10.         OLED_I2C_SendByte(0x40);                //写数据
  11.         OLED_I2C_SendByte(Data);
  12.         OLED_I2C_Stop();
  13. }

  14. /**
  15.   * @brief  OLED设置光标位置
  16.   * @param  Y 以左上角为原点,向下方向的坐标,范围:0~7
  17.   * @param  X 以左上角为原点,向右方向的坐标,范围:0~127
  18.   * @retval 无
  19.   */
  20. void OLED_SetCursor(uint8_t Y, uint8_t X)
  21. {
  22.         OLED_WriteCommand(0xB0 | Y);                                        //设置Y位置
  23.         OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));        //设置X位置低4位
  24.         OLED_WriteCommand(0x00 | (X & 0x0F));                        //设置X位置高4位
  25. }

  26. /**
  27.   * @brief  OLED清屏
  28.   * @param  无
  29.   * @retval 无
  30.   */
  31. void OLED_Clear(void)
  32. {  
  33.         uint8_t i, j;
  34.         for (j = 0; j < 8; j++)
  35.         {
  36.                 OLED_SetCursor(j, 0);
  37.                 for(i = 0; i < 128; i++)
  38.                 {
  39.                         OLED_WriteData(0x00);
  40.                 }
  41.         }
  42. }
  1. /**
  2.   * @brief  OLED显示一个中文
  3.   * @param  Line 行位置,范围:1~4
  4.   * @param  Column 列位置,范围:1~15,注意两个汉字的列位置间隔两个位置
  5.                         比如:       
  6.                         OLED_ShowChinese(1,1,0);第一个汉字
  7.                         OLED_ShowChinese(1,3,1);第二个汉字
  8.   * @param  Select 从汉字库选择汉字索引
  9.   * @retval 无
  10.   */
  11. void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t Select)
  12. {
  13.         uint8_t i;
  14.         OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);                //设置光标位置在上半部分
  15.         for (i = 0; i < 16; i++)
  16.         {
  17.                 OLED_WriteData(OLED_F16x16[Select*2][i]);                        //显示上半部分内容
  18.         }
  19.         OLED_SetCursor((Line - 1) * 2+1, (Column - 1) * 8);                //设置光标位置在上半部分
  20.         for (i = 0; i < 16; i++)
  21.         {
  22.                 OLED_WriteData(OLED_F16x16[Select*2][i+16]);                        //显示上半部分内容
  23.         }
  24. }

  25. /**
  26.   * @brief  OLED显示一个字符
  27.   * @param  Line 行位置,范围:1~4
  28.   * @param  Column 列位置,范围:1~16
  29.   * @param  Char 要显示的一个字符,范围:ASCII可见字符
  30.   * @retval 无
  31.   */
  32. void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
  33. {             
  34.         uint8_t i;
  35.         OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);                //设置光标位置在上半部分
  36.         for (i = 0; i < 8; i++)
  37.         {
  38.                 OLED_WriteData(OLED_F8x16[Char - ' '][i]);                        //显示上半部分内容
  39.         }
  40.         OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);        //设置光标位置在下半部分
  41.         for (i = 0; i < 8; i++)
  42.         {
  43.                 OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);                //显示下半部分内容
  44.         }
  45. }

  46. /**
  47.   * @brief  OLED显示字符串
  48.   * @param  Line 起始行位置,范围:1~4
  49.   * @param  Column 起始列位置,范围:1~16
  50.   * @param  String 要显示的字符串,范围:ASCII可见字符
  51.   * @retval 无
  52.   */
  53. void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
  54. {
  55.         uint8_t i;
  56.         for (i = 0; String[i] != '\0'; i++)
  57.         {
  58.                 OLED_ShowChar(Line, Column + i, String[i]);
  59.         }
  60. }
  1. /**
  2.   * @brief  OLED次方函数
  3.   * @retval 返回值等于X的Y次方
  4.   */
  5. uint32_t OLED_Pow(uint32_t X, uint32_t Y)
  6. {
  7.         uint32_t Result = 1;
  8.         while (Y--)
  9.         {
  10.                 Result *= X;
  11.         }
  12.         return Result;
  13. }

  14. /**
  15.   * @brief  OLED显示数字(十进制,正数)
  16.   * @param  Line 起始行位置,范围:1~4
  17.   * @param  Column 起始列位置,范围:1~16
  18.   * @param  Number 要显示的数字,范围:0~4294967295
  19.   * @param  Length 要显示数字的长度,范围:1~10
  20.   * @retval 无
  21.   */
  22. void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
  23. {
  24.         uint8_t i;
  25.         for (i = 0; i < Length; i++)                                                       
  26.         {
  27.                 OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
  28.         }
  29. }

  30. /**
  31.   * @brief  OLED显示数字(十进制,带符号数)
  32.   * @param  Line 起始行位置,范围:1~4
  33.   * @param  Column 起始列位置,范围:1~16
  34.   * @param  Number 要显示的数字,范围:-2147483648~2147483647
  35.   * @param  Length 要显示数字的长度,范围:1~10
  36.   * @retval 无
  37.   */
  38. void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
  39. {
  40.         uint8_t i;
  41.         uint32_t Number1;
  42.         if (Number >= 0)
  43.         {
  44.                 OLED_ShowChar(Line, Column, '+');
  45.                 Number1 = Number;
  46.         }
  47.         else
  48.         {
  49.                 OLED_ShowChar(Line, Column, '-');
  50.                 Number1 = -Number;
  51.         }
  52.         for (i = 0; i < Length; i++)                                                       
  53.         {
  54.                 OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
  55.         }
  56. }

  57. /**
  58.   * @brief  OLED显示数字(十六进制,正数)
  59.   * @param  Line 起始行位置,范围:1~4
  60.   * @param  Column 起始列位置,范围:1~16
  61.   * @param  Number 要显示的数字,范围:0~0xFFFFFFFF
  62.   * @param  Length 要显示数字的长度,范围:1~8
  63.   * @retval 无
  64.   */
  65. void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
  66. {
  67.         uint8_t i, SingleNumber;
  68.         for (i = 0; i < Length; i++)                                                       
  69.         {
  70.                 SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
  71.                 if (SingleNumber < 10)
  72.                 {
  73.                         OLED_ShowChar(Line, Column + i, SingleNumber + '0');
  74.                 }
  75.                 else
  76.                 {
  77.                         OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
  78.                 }
  79.         }
  80. }

  81. /**
  82.   * @brief  OLED显示数字(二进制,正数)
  83.   * @param  Line 起始行位置,范围:1~4
  84.   * @param  Column 起始列位置,范围:1~16
  85.   * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  86.   * @param  Length 要显示数字的长度,范围:1~16
  87.   * @retval 无
  88.   */
  89. void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
  90. {
  91.         uint8_t i;
  92.         for (i = 0; i < Length; i++)                                                       
  93.         {
  94.                 OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
  95.         }
  96. }
  1. /**
  2.   * @brief  OLED初始化
  3.   * @param  无
  4.   * @retval 无
  5.   */
  6. void OLED_Init(void)
  7. {
  8.         uint32_t i, j;
  9.        
  10.         for (i = 0; i < 1000; i++)                        //上电延时
  11.         {
  12.                 for (j = 0; j < 1000; j++);
  13.         }
  14.        
  15.         OLED_I2C_Init();                        //端口初始化
  16.        
  17.         OLED_WriteCommand(0xAE);        //关闭显示
  18.        
  19.         OLED_WriteCommand(0xD5);        //设置显示时钟分频比/振荡器频率
  20.         OLED_WriteCommand(0x80);
  21.        
  22.         OLED_WriteCommand(0xA8);        //设置多路复用率
  23.         OLED_WriteCommand(0x3F);
  24.        
  25.         OLED_WriteCommand(0xD3);        //设置显示偏移
  26.         OLED_WriteCommand(0x00);
  27.        
  28.         OLED_WriteCommand(0x40);        //设置显示开始行
  29.        
  30.         OLED_WriteCommand(0xA1);        //设置左右方向,0xA1正常 0xA0左右反置
  31.        
  32.         OLED_WriteCommand(0xC8);        //设置上下方向,0xC8正常 0xC0上下反置

  33.         OLED_WriteCommand(0xDA);        //设置COM引脚硬件配置
  34.         OLED_WriteCommand(0x12);
  35.        
  36.         OLED_WriteCommand(0x81);        //设置对比度控制
  37.         OLED_WriteCommand(0xCF);

  38.         OLED_WriteCommand(0xD9);        //设置预充电周期
  39.         OLED_WriteCommand(0xF1);

  40.         OLED_WriteCommand(0xDB);        //设置VCOMH取消选择级别
  41.         OLED_WriteCommand(0x30);

  42.         OLED_WriteCommand(0xA4);        //设置整个显示打开/关闭

  43.         OLED_WriteCommand(0xA6);        //设置正常/倒转显示

  44.         OLED_WriteCommand(0x8D);        //设置充电泵
  45.         OLED_WriteCommand(0x14);

  46.         OLED_WriteCommand(0xAF);        //开启显示
  47.                
  48.         OLED_Clear();                                //OLED清屏
  49. }

在主程序中,添加显示函数:
  1. OLED_Init();   //OLED初始化
  2.         OLED_ShowString(1,2,"21IC lun tan ");
  3.         OLED_ShowString(2,2,"CW32L010 TEST");
  4.         OLED_ShowString(3,2,"congcong gegge");
  5.         OLED_ShowString(4,2,"2024-12-30    ");
实物图片如下:
图片16.jpg

后记:从移植的角度来说,代码移植很方便,只需要定义SDA,SCL两根线的IO口,初始化配置,后面直接调用模拟IIC写数据和指令的函数即可,只是在调试的时候注意下,所使用的IO口没有被板载的资源所占用就可以。

小夏天的大西瓜 发表于 2025-1-8 21:28 | 显示全部楼层
如何不用软件进行字母输出?
 楼主| 聪聪哥哥 发表于 2025-1-9 12:56 | 显示全部楼层
小夏天的大西瓜 发表于 2025-1-8 21:28
如何不用软件进行字母输出?

这种OLED得貌似只能做字库显示,屏幕本身没有字库得
小小蚂蚁举千斤 发表于 2025-1-11 19:12 | 显示全部楼层
移植调试IIC
OKAKAKO 发表于 2025-1-22 09:01 | 显示全部楼层
从移植的角度来说,代码移植很方便,只需要定义SDA,SCL两根线的IO口,初始化配置,后面直接调用模拟IIC写数据和指令的函数即可
星辰大海不退缩 发表于 2025-1-23 19:15 | 显示全部楼层
移植调试IIC非常不错的
AdaMaYun 发表于 2025-1-25 22:54 | 显示全部楼层
使用模拟IIC驱动OLED的显示速率会慢一点
您需要登录后才可以回帖 登录 | 注册

本版积分规则

108

主题

309

帖子

1

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