[AT32L021] 【AT-START-L021测评】硬件I2C/IIC 驱动OLED

[复制链接]
 楼主| 南来之风 发表于 2024-12-23 13:24 | 显示全部楼层 |阅读模式
先看效果:

3D99B7A8-CCC2-4318-8481-278362601878-16613-00000F1426BA7F70.gif

首先进行OLED初始化:
  1. void OLED_Init(void)
  2. {        
  3.         delay_ms(1000);
  4.         
  5.         WriteCmd(0xAE);//--turn off oled panel
  6.         WriteCmd(0x00);//---set low column address
  7.         WriteCmd(0x10);//---set high column address
  8.         WriteCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  9.         WriteCmd(0x81);//--set contrast control register
  10.         WriteCmd(0xCF);// Set SEG Output Current Brightness
  11.         WriteCmd(0xA1);//--Set SEG/Column Mapping     0xa0���ҷ��� 0xa1����
  12.         WriteCmd(0xC8);//Set COM/Row Scan Direction   0xc0���·��� 0xc8����
  13.         WriteCmd(0xA6);//--set normal display
  14.         WriteCmd(0xA8);//--set multiplex ratio(1 to 64)
  15.         WriteCmd(0x3f);//--1/64 duty
  16.         WriteCmd(0xD3);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)
  17.         WriteCmd(0x00);//-not offset
  18.         WriteCmd(0xd5);//--set display clock divide ratio/oscillator frequency
  19.         WriteCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
  20.         WriteCmd(0xD9);//--set pre-charge period
  21.         WriteCmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  22.         WriteCmd(0xDA);//--set com pins hardware configuration
  23.         WriteCmd(0x12);
  24.         WriteCmd(0xDB);//--set vcomh
  25.         WriteCmd(0x40);//Set VCOM Deselect Level
  26.         WriteCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
  27.         WriteCmd(0x02);//
  28.         WriteCmd(0x8D);//--set Charge Pump enable/disable
  29.         WriteCmd(0x14);//--set(0x10) disable
  30.         WriteCmd(0xA4);// Disable Entire Display On (0xa4/0xa5)
  31.         WriteCmd(0xA6);// Disable Inverse Display On (0xa6/a7)
  32.         OLED_Clear();
  33.         WriteCmd(0xAF);        //Set display on added by sensoryoung
  34.         delay_ms(200);
  35. }

然后刷新屏幕:
  1. void OLED_Refresh(void)
  2. {
  3.         uint8_t i,n;
  4.         for(i=0;i<8;i++)
  5.         {
  6.                 WriteCmd(0xb0+i);
  7.                 WriteCmd(0x00);
  8.                 WriteCmd(0x10);

  9.                 for(n=0;n<128;n++)
  10.                 {
  11.                         WriteDat(OLED_GRAM[n][i]);
  12.                 }
  13.   }
  14. }
这里有关键的两个函数:WriteCmd 与 WriteDat。实现如下:

  1. /**************************************************************
  2.          Prototype      : void WriteCmd(uint8_t IIC_Command)
  3.          Parameters     : IIC_Command
  4.          return                                        : none
  5.          Description    : 写命令(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
  6.                       向0x00写入命令)
  7. ***************************************************************/
  8. void WriteCmd(uint8_t IIC_Command)
  9. {
  10.         HAL_I2C_WriteByte(0x00, IIC_Command);
  11. }

  12. /**************************************************************
  13.          Prototype      : void WriteDat(uint8_t IIC_Data)
  14.          Parameters     : IIC_Data
  15.          return                                        : none
  16.          Description    : 写数据(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
  17.                       向0x40写入数据)
  18. ***************************************************************/
  19. void WriteDat(uint8_t IIC_Data)
  20. {
  21.         HAL_I2C_WriteByte(0x40, IIC_Data);
在调用I2C模块向总线发送数据之前,封装了一下:

  1. /***************************************************
  2.     I2C总线传出数据函数:
  3.                 addr  :    要写入的地址(OLED的地址一般为0x40;指令地址为0x00)
  4.                 data  :    要写入的数据
  5. ***************************************************/
  6. void HAL_I2C_WriteByte(uint8_t addr,uint8_t data)
  7. {
  8.         //uint8_t TxData[2] = {addr,data};
  9.         uint8_t TxData[2];
  10.         TxData[0] = addr;
  11.         TxData[1] = data;
  12.   if((i2c_status = i2c_master_transmit(&hi2cx, 0X78, TxData, 2, I2C_TIMEOUT)) != I2C_OK)
  13.   {
  14.     error_handler(i2c_status);
  15.   }        
  16. }
实际效果还不错,完整代码如下:
  1. /*Reference: https://blog.csdn.net/Reasally/article/details/126789505*/
  2. #include "oled.h"
  3. #include "stdlib.h"
  4. #include "oledfont.h"           

  5. //For ARTEY ATL021
  6. extern void error_handler(uint32_t error_code);
  7. extern i2c_handle_type hi2cx;
  8. extern i2c_status_type i2c_status;
  9. #define I2C_TIMEOUT                      0xFFFFFFF

  10. uint8_t OLED_GRAM[144][8];

  11. //���Ժ���
  12. void OLED_ColorTurn(uint8_t i)
  13. {
  14.         if(i==0)
  15.                 {
  16.                         WriteCmd(0xA6);
  17.                 }
  18.         if(i==1)
  19.                 {
  20.                         WriteCmd(0xA7);
  21.                 }
  22. }

  23. //��Ļ��ת180��
  24. void OLED_DisplayTurn(uint8_t i)
  25. {
  26.         if(i==0)
  27.                 {
  28.                         WriteCmd(0xC8);
  29.                         WriteCmd(0xA1);
  30.                 }
  31.         if(i==1)
  32.                 {
  33.                         WriteCmd(0xC0);
  34.                         WriteCmd(0xA0);
  35.                 }
  36. }

  37. //��ʱ
  38. void IIC_delay(void)
  39. {
  40.         uint16_t t=300;
  41.         while(t--);
  42. }

  43. /***************************************************
  44.     I2C总线传出数据函数:
  45.                 addr  :    要写入的地址(OLED的地址一般为0x40;指令地址为0x00)
  46.                 data  :    要写入的数据
  47. ***************************************************/
  48. void HAL_I2C_WriteByte(uint8_t addr,uint8_t data)
  49. {
  50.         //uint8_t TxData[2] = {addr,data};
  51.         uint8_t TxData[2];
  52.         TxData[0] = addr;
  53.         TxData[1] = data;
  54.   if((i2c_status = i2c_master_transmit(&hi2cx, 0X78, TxData, 2, I2C_TIMEOUT)) != I2C_OK)
  55.   {
  56.     error_handler(i2c_status);
  57.   }        
  58. }

  59. /**************************************************************
  60.          Prototype      : void WriteCmd(uint8_t IIC_Command)
  61.          Parameters     : IIC_Command
  62.          return                                        : none
  63.          Description    : 写命令(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
  64.                       向0x00写入命令)
  65. ***************************************************************/
  66. void WriteCmd(uint8_t IIC_Command)
  67. {
  68.         HAL_I2C_WriteByte(0x00, IIC_Command);
  69. }

  70. /**************************************************************
  71.          Prototype      : void WriteDat(uint8_t IIC_Data)
  72.          Parameters     : IIC_Data
  73.          return                                        : none
  74.          Description    : 写数据(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
  75.                       向0x40写入数据)
  76. ***************************************************************/
  77. void WriteDat(uint8_t IIC_Data)
  78. {
  79.         HAL_I2C_WriteByte(0x40, IIC_Data);
  80. }


  81. //����һ���ֽ�
  82. //mode:����/�����־ 0,��ʾ����;1,��ʾ����;
  83. void OLED_WR_Byte(uint8_t dat,uint8_t mode)
  84. {
  85.         
  86.         if(mode){
  87.                 //Send_Byte(0x40);
  88.                 WriteDat(dat);
  89.         }
  90.         else{
  91.                 //Send_Byte(0x00);
  92.                 WriteCmd(dat);
  93.         }
  94.     //Send_Byte(dat);
  95.     //I2C_Stop();
  96. }



  97. //����OLED��ʾ
  98. void OLED_DisPlay_On(void)
  99. {
  100.         WriteCmd(0x8D);
  101.         WriteCmd(0x14);
  102.         WriteCmd(0xAF);
  103. }

  104. //�ر�OLED��ʾ
  105. void OLED_DisPlay_Off(void)
  106. {
  107.         WriteCmd(0x8D);
  108.         WriteCmd(0x10);
  109.         WriteCmd(0xAE);
  110. }

  111. //�����Դ浽OLED        
  112. void OLED_Refresh(void)
  113. {
  114.         uint8_t i,n;
  115.         for(i=0;i<8;i++)
  116.         {
  117.                 WriteCmd(0xb0+i);
  118.                 WriteCmd(0x00);
  119.                 WriteCmd(0x10);

  120.                 for(n=0;n<128;n++)
  121.                 {
  122.                         WriteDat(OLED_GRAM[n][i]);
  123.                 }
  124.   }
  125. }
  126. //��������
  127. void OLED_Clear(void)
  128. {
  129.         uint8_t i,n;
  130.         for(i=0;i<8;i++)
  131.         {
  132.            for(n=0;n<128;n++)
  133.                         {
  134.                          OLED_GRAM[n][i]=0;//�����������
  135.                         }
  136.   }
  137. }

  138. //����
  139. //x:0~127
  140. //y:0~63
  141. //t:1 ��� 0,���        
  142. void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t)
  143. {
  144.         uint8_t i,m,n;
  145.         i=y/8;
  146.         m=y%8;
  147.         n=1<<m;
  148.         if(t){OLED_GRAM[x][i]|=n;}
  149.         else
  150.         {
  151.                 OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  152.                 OLED_GRAM[x][i]|=n;
  153.                 OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  154.         }
  155. }

  156. //����
  157. //x1,y1:�������
  158. //x2,y2:��������
  159. void OLED_DrawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t mode)
  160. {
  161.         uint16_t t;
  162.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  163.         int incx,incy,uRow,uCol;
  164.         delta_x=x2-x1; //������������
  165.         delta_y=y2-y1;
  166.         uRow=x1;//�����������
  167.         uCol=y1;
  168.         if(delta_x>0)incx=1; //���õ�������
  169.         else if (delta_x==0)incx=0;//��ֱ��
  170.         else {incx=-1;delta_x=-delta_x;}
  171.         if(delta_y>0)incy=1;
  172.         else if (delta_y==0)incy=0;//ˮƽ��
  173.         else {incy=-1;delta_y=-delta_x;}
  174.         if(delta_x>delta_y)distance=delta_x; //ѡȡ��������������
  175.         else distance=delta_y;
  176.         for(t=0;t<distance+1;t++)
  177.         {
  178.                 OLED_DrawPoint(uRow,uCol,mode);//����
  179.                 xerr+=delta_x;
  180.                 yerr+=delta_y;
  181.                 if(xerr>distance)
  182.                 {
  183.                         xerr-=distance;
  184.                         uRow+=incx;
  185.                 }
  186.                 if(yerr>distance)
  187.                 {
  188.                         yerr-=distance;
  189.                         uCol+=incy;
  190.                 }
  191.         }
  192. }
  193. //x,y:Բ������
  194. //r:Բ�İ뾶
  195. void OLED_DrawCircle(uint8_t x,uint8_t y,uint8_t r)
  196. {
  197.         int a, b,num;
  198.     a = 0;
  199.     b = r;
  200.     while(2 * b * b >= r * r)      
  201.     {
  202.         OLED_DrawPoint(x + a, y - b,1);
  203.         OLED_DrawPoint(x - a, y - b,1);
  204.         OLED_DrawPoint(x - a, y + b,1);
  205.         OLED_DrawPoint(x + a, y + b,1);

  206.         OLED_DrawPoint(x + b, y + a,1);
  207.         OLED_DrawPoint(x + b, y - a,1);
  208.         OLED_DrawPoint(x - b, y - a,1);
  209.         OLED_DrawPoint(x - b, y + a,1);
  210.         
  211.         a++;
  212.         num = (a * a + b * b) - r*r;//���㻭�ĵ���Բ�ĵľ���
  213.         if(num > 0)
  214.         {
  215.             b--;
  216.             a--;
  217.         }
  218.     }
  219. }



  220. //��ָ��λ����ʾһ���ַ�,���������ַ�
  221. //x:0~127
  222. //y:0~63
  223. //size1:ѡ������ 6x8/6x12/8x16/12x24
  224. //mode:0,��ɫ��ʾ;1,������ʾ
  225. void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size1,uint8_t mode)
  226. {
  227.         uint8_t i,m,temp,size2,chr1;
  228.         uint8_t x0=x,y0=y;
  229.         if(size1==8)size2=6;
  230.         else size2=(size1/8+((size1%8)?1:0))*(size1/2);  //�õ�����һ���ַ���Ӧ������ռ���ֽ���
  231.         chr1=chr-' ';  //����ƫ�ƺ��ֵ
  232.         for(i=0;i<size2;i++)
  233.         {
  234.                 if(size1==8)
  235.                           {temp=asc2_0806[chr1][i];} //����0806����
  236.                 else if(size1==12)
  237.         {temp=asc2_1206[chr1][i];} //����1206����
  238.                 else if(size1==16)
  239.         {temp=asc2_1608[chr1][i];} //����1608����
  240.                 else if(size1==24)
  241.         {temp=asc2_2412[chr1][i];} //����2412����
  242.                 else return;
  243.                 for(m=0;m<8;m++)
  244.                 {
  245.                         if(temp&0x01)OLED_DrawPoint(x,y,mode);
  246.                         else OLED_DrawPoint(x,y,!mode);
  247.                         temp>>=1;
  248.                         y++;
  249.                 }
  250.                 x++;
  251.                 if((size1!=8)&&((x-x0)==size1/2))
  252.                 {x=x0;y0=y0+8;}
  253.                 y=y0;
  254.   }
  255. }


  256. //��ʾ�ַ���
  257. //x,y:�������  
  258. //size1:�����С
  259. //*chr:�ַ�����ʼ��ַ
  260. //mode:0,��ɫ��ʾ;1,������ʾ
  261. void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t size1,uint8_t mode)
  262. {
  263.         while((*chr>=' ')&&(*chr<='~'))//�ж��Dz��ǷǷ��ַ�!
  264.         {
  265.                 OLED_ShowChar(x,y,*chr,size1,mode);
  266.                 if(size1==8)x+=6;
  267.                 else x+=size1/2;
  268.                 chr++;
  269.   }
  270. }

  271. //m^n
  272. uint32_t OLED_Pow(uint8_t m,uint8_t n)
  273. {
  274.         uint32_t result=1;
  275.         while(n--)
  276.         {
  277.           result*=m;
  278.         }
  279.         return result;
  280. }

  281. //��ʾ����
  282. //x,y :�������
  283. //num :Ҫ��ʾ������
  284. //len :���ֵ�λ��
  285. //size:�����С
  286. //mode:0,��ɫ��ʾ;1,������ʾ
  287. void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size1,uint8_t mode)
  288. {
  289.         uint8_t t,temp,m=0;
  290.         if(size1==8)m=2;
  291.         for(t=0;t<len;t++)
  292.         {
  293.                 temp=(num/OLED_Pow(10,len-t-1))%10;
  294.                         if(temp==0)
  295.                         {
  296.                                 OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
  297.       }
  298.                         else
  299.                         {
  300.                           OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
  301.                         }
  302.   }
  303. }

  304. //��ʾ����
  305. //x,y:�������
  306. //num:���ֶ�Ӧ�����
  307. //mode:0,��ɫ��ʾ;1,������ʾ
  308. void OLED_ShowChinese(uint8_t x,uint8_t y,uint8_t num,uint8_t size1,uint8_t mode)
  309. {
  310.         uint8_t m,temp;
  311.         uint8_t x0=x,y0=y;
  312.         uint16_t i,size3=(size1/8+((size1%8)?1:0))*size1;  //�õ�����һ���ַ���Ӧ������ռ���ֽ���
  313.         for(i=0;i<size3;i++)
  314.         {
  315.                 if(size1==16)
  316.                                 {temp=Hzk1[num][i];}//����16*16����
  317.                 else if(size1==24)
  318.                                 {temp=Hzk2[num][i];}//����24*24����
  319.                 else if(size1==32)      
  320.                                 {temp=Hzk3[num][i];}//����32*32����
  321.                 else if(size1==64)
  322.                                 {temp=Hzk4[num][i];}//����64*64����
  323.                 else return;
  324.                 for(m=0;m<8;m++)
  325.                 {
  326.                         if(temp&0x01)OLED_DrawPoint(x,y,mode);
  327.                         else OLED_DrawPoint(x,y,!mode);
  328.                         temp>>=1;
  329.                         y++;
  330.                 }
  331.                 x++;
  332.                 if((x-x0)==size1)
  333.                 {x=x0;y0=y0+8;}
  334.                 y=y0;
  335.         }
  336. }

  337. //num ��ʾ���ֵĸ���
  338. //space ÿһ����ʾ�ļ��
  339. //mode:0,��ɫ��ʾ;1,������ʾ
  340. void OLED_ScrollDisplay(uint8_t num,uint8_t space,uint8_t mode)
  341. {
  342.         uint8_t i,n,t=0,m=0,r;
  343.         while(1)
  344.         {
  345.                 if(m==0)
  346.                 {
  347.             OLED_ShowChinese(128,24,t,16,mode); //д��һ�����ֱ�����OLED_GRAM[][]������
  348.                         t++;
  349.                 }
  350.                 if(t==num)
  351.                         {
  352.                                 for(r=0;r<16*space;r++)      //��ʾ���
  353.                                  {
  354.                                         for(i=1;i<144;i++)
  355.                                                 {
  356.                                                         for(n=0;n<8;n++)
  357.                                                         {
  358.                                                                 OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
  359.                                                         }
  360.                                                 }
  361.            OLED_Refresh();
  362.                                  }
  363.         t=0;
  364.       }
  365.                 m++;
  366.                 if(m==16){m=0;}
  367.                 for(i=1;i<144;i++)   //ʵ������
  368.                 {
  369.                         for(n=0;n<8;n++)
  370.                         {
  371.                                 OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
  372.                         }
  373.                 }
  374.                 OLED_Refresh();
  375.         }
  376. }

  377. //x,y���������
  378. //sizex,sizey,ͼƬ����
  379. //BMP[]��Ҫд���ͼƬ����
  380. //mode:0,��ɫ��ʾ;1,������ʾ
  381. void OLED_ShowPicture(uint8_t x,uint8_t y,uint8_t sizex,uint8_t sizey,uint8_t BMP[],uint8_t mode)
  382. {
  383.         uint16_t j=0;
  384.         uint8_t i,n,temp,m;
  385.         uint8_t x0=x,y0=y;
  386.         sizey=sizey/8+((sizey%8)?1:0);
  387.         for(n=0;n<sizey;n++)
  388.         {
  389.                  for(i=0;i<sizex;i++)
  390.                  {
  391.                                 temp=BMP[j];
  392.                                 j++;
  393.                                 for(m=0;m<8;m++)
  394.                                 {
  395.                                         if(temp&0x01)OLED_DrawPoint(x,y,mode);
  396.                                         else OLED_DrawPoint(x,y,!mode);
  397.                                         temp>>=1;
  398.                                         y++;
  399.                                 }
  400.                                 x++;
  401.                                 if((x-x0)==sizex)
  402.                                 {
  403.                                         x=x0;
  404.                                         y0=y0+8;
  405.                                 }
  406.                                 y=y0;
  407.      }
  408.          }
  409. }
  410. //OLED�ij�ʼ��
  411. void OLED_Init(void)
  412. {        
  413.         delay_ms(1000);
  414.         
  415.         WriteCmd(0xAE);//--turn off oled panel
  416.         WriteCmd(0x00);//---set low column address
  417.         WriteCmd(0x10);//---set high column address
  418.         WriteCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  419.         WriteCmd(0x81);//--set contrast control register
  420.         WriteCmd(0xCF);// Set SEG Output Current Brightness
  421.         WriteCmd(0xA1);//--Set SEG/Column Mapping     0xa0���ҷ��� 0xa1����
  422.         WriteCmd(0xC8);//Set COM/Row Scan Direction   0xc0���·��� 0xc8����
  423.         WriteCmd(0xA6);//--set normal display
  424.         WriteCmd(0xA8);//--set multiplex ratio(1 to 64)
  425.         WriteCmd(0x3f);//--1/64 duty
  426.         WriteCmd(0xD3);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)
  427.         WriteCmd(0x00);//-not offset
  428.         WriteCmd(0xd5);//--set display clock divide ratio/oscillator frequency
  429.         WriteCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
  430.         WriteCmd(0xD9);//--set pre-charge period
  431.         WriteCmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  432.         WriteCmd(0xDA);//--set com pins hardware configuration
  433.         WriteCmd(0x12);
  434.         WriteCmd(0xDB);//--set vcomh
  435.         WriteCmd(0x40);//Set VCOM Deselect Level
  436.         WriteCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
  437.         WriteCmd(0x02);//
  438.         WriteCmd(0x8D);//--set Charge Pump enable/disable
  439.         WriteCmd(0x14);//--set(0x10) disable
  440.         WriteCmd(0xA4);// Disable Entire Display On (0xa4/0xa5)
  441.         WriteCmd(0xA6);// Disable Inverse Display On (0xa6/a7)
  442.         OLED_Clear();
  443.         WriteCmd(0xAF);        //Set display on added by sensoryoung
  444.         delay_ms(200);
  445. }




TimeRiddle 发表于 2025-3-25 11:41 | 显示全部楼层
硬件IIC,这个好,用上DMA更好
justin0407 发表于 2025-3-31 13:42 | 显示全部楼层
IIC速率最高1Mbps,刷稍为大一点的OLED就会吃力。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

69

主题

290

帖子

2

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