[通用8051核FLASH系列] 【芯圣SDK-HC89F0541测评】+ OLED(硬件I2C)

[复制链接]
1476|6
 楼主| 比神乐 发表于 2020-7-12 19:45 | 显示全部楼层 |阅读模式
本帖最后由 芯圣电子官方QQ 于 2023-7-25 14:18 编辑

原来搞了个模拟时序,现在是硬件I2C驱动OLED.
SCK:P0_1;
SDA:P0_0;
原理图:
2.jpg
代码:
  1. #define        ALLOCATE_EXTERN
  2. #include "HC89F0541.h"
  3. #include "oledfont.h"
  4. #include "oled.h"

  5. #define SCL        P0_1                                           //I2C时钟控制位
  6. #define SDA P0_0                                    //I2C数据传送位







  7. //OLED的显存
  8. //存放格式如下.
  9. //[0]0 1 2 3 ... 127        
  10. //[1]0 1 2 3 ... 127        
  11. //[2]0 1 2 3 ... 127        
  12. //[3]0 1 2 3 ... 127        
  13. //[4]0 1 2 3 ... 127        
  14. //[5]0 1 2 3 ... 127        
  15. //[6]0 1 2 3 ... 127        
  16. //[7]0 1 2 3 ... 127                           
  17. /**
  18.   * @说明          延时函数
  19.   * @参数          fui_i : 延时时间
  20.   * @返回值 无
  21.   * @注         Fcpu = 16MHz,fui_i = 1时,延时时间约为1Ms
  22.   */
  23. void Delay_ms(unsigned int fui_i)
  24. {
  25.         unsigned int fui_j;
  26.         for(;fui_i > 0;fui_i --)
  27.         for(fui_j = 1596;fui_j > 0;fui_j --);
  28. }
  29. /**
  30.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Write_I2C_Data 向OLED写入数据
  31.   * @param  I2C_Data:数据
  32.   * @retval 无
  33.   */
  34. static void Write_I2C_Data(uint8_t I2C_Data)//写数据
  35. {
  36.    
  37.         IICCON &=~ 0x08;                //清除中断标志位        
  38.         IICCON |= 0x20;                         //起始位发送起始信号
  39.         while((!(IICCON&0x08))&&(IICSTA!=0x08));
  40.         IICCON &=~ 0x20;                //起始位停止起始信号               
  41.         
  42.         IICCON &=~ 0x08;                //清除中断标志位
  43.         IICDAT = OLED_ADDS;                //写入器件地址
  44.         while(IICSTA!=0x18);
  45.         
  46.         IICCON &=~ 0x08;                //清除中断标志位                                
  47.         IICDAT = 0x40;                //写入地址
  48.         while(IICSTA!=0x28);
  49.         IICCON &=~ 0x08;                //清除中断标志位
  50.         IICDAT = I2C_Data;                //写入数据
  51.         while(IICSTA!=0x28);
  52.         IICCON &=~ 0x08;                //清除中断标志位
  53.         IICCON |= 0x10;                 //停止位发送停止信号
  54.                                 
  55. }

  56. /**
  57.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Write_I2C_Command,向OLED写入命令
  58.   * @param  I2C_Command
  59.   * @retval 无
  60.   */
  61. static void Write_I2C_Command(uint8_t I2C_Command)//写命令
  62. {

  63.                 IICCON &=~ 0x08;                //清除中断标志位        
  64.         IICCON |= 0x20;                         //起始位发送起始信号
  65.         while((!(IICCON&0x08))&&(IICSTA!=0x08));
  66.         IICCON &=~ 0x20;                //起始位停止起始信号               
  67.         
  68.         IICCON &=~ 0x08;                //清除中断标志位
  69.         IICDAT = OLED_ADDS;                //写入器件地址
  70.         while(IICSTA!=0x18);
  71.         
  72.         IICCON &=~ 0x08;                //清除中断标志位                                
  73.         IICDAT = 0x00;                //写入地址
  74.         while(IICSTA!=0x28);
  75.         IICCON &=~ 0x08;                //清除中断标志位
  76.         IICDAT = I2C_Command;                //写入数据
  77.         while(IICSTA!=0x28);
  78.         IICCON &=~ 0x08;                //清除中断标志位
  79.         IICCON |= 0x10;                 //停止位发送停止信号
  80. }


  81. void OLED_WR_Byte(unsigned dat,unsigned cmd)
  82. {
  83.         if(cmd)
  84.                 Write_I2C_Data(dat);
  85.         else
  86.                 Write_I2C_Command(dat);
  87. }

  88. /********************************************
  89. // fill_Picture
  90. ********************************************/
  91. void fill_picture(uint8_t fill_Data)
  92. {
  93.         uint8_t m,n;
  94.         for(m=0; m<8; m++)
  95.         {
  96.                 OLED_WR_Byte(0xb0+m,0);                //page0-page1
  97.                 OLED_WR_Byte(0x00,0);                //low column start address
  98.                 OLED_WR_Byte(0x10,0);                //high column start address
  99.                 for(n=0; n<128; n++)
  100.                 {
  101.                         OLED_WR_Byte(fill_Data,1);
  102.                 }
  103.         }
  104. }


  105. //坐标设置
  106. void OLED_Set_Pos(uint8_t x, uint8_t y)
  107. {         
  108.         OLED_WR_Byte(0xb0+y, OLED_CMD);
  109.         OLED_WR_Byte(((x&0xf0)>>4)|0x10, OLED_CMD);
  110.         OLED_WR_Byte((x&0x0f), OLED_CMD);
  111. }            


  112. //开启OLED显示   
  113. void OLED_Display_On(void)
  114. {
  115.         OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
  116.         OLED_WR_Byte(0X14, OLED_CMD);  //DCDC ON
  117.         OLED_WR_Byte(0XAF, OLED_CMD);  //DISPLAY ON
  118. }


  119. //关闭OLED显示     
  120. void OLED_Display_Off(void)
  121. {
  122.         OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
  123.         OLED_WR_Byte(0X10, OLED_CMD);  //DCDC OFF
  124.         OLED_WR_Byte(0XAE, OLED_CMD);  //DISPLAY OFF
  125. }        


  126. //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!         
  127. void OLED_Clear(void)  
  128. {  
  129.         uint8_t i,n;                    
  130.         for(i=0; i<8; i++)  
  131.         {  
  132.                 OLED_WR_Byte (0xb0+i, OLED_CMD);    //设置页地址(0~7)
  133.                 OLED_WR_Byte (0x00,   OLED_CMD);      //设置显示位置—列低地址
  134.                 OLED_WR_Byte (0x10,   OLED_CMD);      //设置显示位置—列高地址   
  135.                 for(n=0; n<128; n++)
  136.                         OLED_WR_Byte(0, OLED_DATA);
  137.         }
  138. }


  139. void OLED_ON(void)  
  140. {  
  141.         uint8_t i,n;                    
  142.         for(i=0; i<8; i++)  
  143.         {  
  144.                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
  145.                 OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
  146.                 OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
  147.                 for(n=0; n<128; n++)
  148.                         OLED_WR_Byte(1, OLED_DATA);
  149.         }
  150. }


  151. //在指定位置显示一个字符,包括部分字符
  152. //x:0~127
  153. //y:0~63
  154. //mode:0,反白显示;1,正常显示                                 
  155. //size:选择字体 16/12
  156. void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
  157. {              
  158.         uint8_t c=0,i=0;        
  159.         c=chr-' ';//得到偏移后的值                        
  160.         if(x>Max_Column-1)
  161.         {
  162.                 x = 0;
  163.                 y = y+2;
  164.         }
  165.         if(Char_Size == 16)
  166.         {
  167.                 OLED_Set_Pos(x, y);        
  168.                 for(i=0; i<8; i++)
  169.                         OLED_WR_Byte(F8X16[c*16 + i], OLED_DATA);
  170.                
  171.                 OLED_Set_Pos(x, y+1);
  172.                 for(i=0; i<8; i++)
  173.                         OLED_WR_Byte(F8X16[c*16 + i + 8], OLED_DATA);
  174.         }
  175.         else
  176.         {        
  177.                 OLED_Set_Pos(x, y);
  178.                 for(i=0; i<6; i++)
  179.                         OLED_WR_Byte(F6x8[c][i], OLED_DATA);
  180.         }
  181. }


  182. //m^n函数
  183. uint32_t OLED_pow(uint8_t m, uint8_t n)
  184. {
  185.         uint32_t result = 1;         
  186.         while(n--)
  187.                 result *= m;   
  188.         
  189.         return result;
  190. }                                 


  191. //显示2个数字
  192. //x,y :起点坐标         
  193. //len :数字的位数
  194. //size:字体大小
  195. //mode:模式        0,填充模式;1,叠加模式
  196. //num:数值(0~4294967295);                           
  197. void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size2)
  198. {                 
  199.         uint8_t t,temp;
  200.         uint8_t enshow = 0;                                                   
  201.         for(t=0; t<len; t++)
  202.         {
  203.                 temp = (num/OLED_pow(10, len-t-1)) %10;
  204.                 if(enshow == 0 && t<(len-1))
  205.                 {
  206.                         if(temp == 0)
  207.                         {
  208.                                 OLED_ShowChar(x+(size2/2)*t, y, ' ', size2);
  209.                                 continue;
  210.                         }
  211.                         else
  212.                                 enshow = 1;                           
  213.                 }
  214.                  OLED_ShowChar(x+(size2/2)*t, y, temp+'0', size2);
  215.         }
  216. }


  217. //显示一个字符号串
  218. void OLED_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t Char_Size)
  219. {
  220.         uint8_t j=0;
  221.         while (chr[j] != '\0')
  222.         {               
  223.                 OLED_ShowChar(x, y, chr[j], Char_Size);
  224.                 x += 8;
  225.                 if(x>120)
  226.                 {
  227.                         x=0;
  228.                         y+=2;
  229.                 }
  230.                 j++;
  231.         }
  232. }


  233. //显示汉字
  234. void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no)
  235. {                                 
  236.         uint8_t t,adder=0;
  237.         OLED_Set_Pos(x,y);        
  238.         for(t=0;t<16;t++)
  239.         {
  240.                 OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
  241.                 adder+=1;
  242.         }        
  243.         OLED_Set_Pos(x,y+1);        
  244.         for(t=0;t<16;t++)
  245.         {        
  246.                 OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
  247.                 adder+=1;
  248.         }                                       
  249. }
  250. /***********功能描述:
  251. 显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7
  252. *****************/
  253. void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1, uint8_t BMP[])
  254. {         
  255.         unsigned int j=0;
  256.         uint8_t x,y;

  257.         if(y1%8 == 0)
  258.                 y = y1/8;      
  259.         else
  260.                 y = y1/8 + 1;
  261.         for(y=y0; y<y1; y++)
  262.         {
  263.                 OLED_Set_Pos(x0, y);
  264.                 for(x=x0; x<x1; x++)
  265.                 {      
  266.                         OLED_WR_Byte(BMP[j++], OLED_DATA);                    
  267.                 }
  268.         }
  269. }

  270. //初始化SSD1306                                            
  271. void OLED_Init(void)
  272. {         
  273.         Delay_ms(100);
  274.         OLED_WR_Byte(0xAE,OLED_CMD);//关闭显示
  275.         
  276.         OLED_WR_Byte(0x40,OLED_CMD);//---set low column address
  277.         OLED_WR_Byte(0xB0,OLED_CMD);//---set high column address

  278.         OLED_WR_Byte(0xC8,OLED_CMD);//-not offset

  279.         OLED_WR_Byte(0x81,OLED_CMD);//设置对比度
  280.         OLED_WR_Byte(0xff,OLED_CMD);

  281.         OLED_WR_Byte(0xa1,OLED_CMD);//段重定向设置

  282.         OLED_WR_Byte(0xa6,OLED_CMD);//
  283.         
  284.         OLED_WR_Byte(0xa8,OLED_CMD);//设置驱动路数
  285.         OLED_WR_Byte(0x1f,OLED_CMD);
  286.         
  287.         OLED_WR_Byte(0xd3,OLED_CMD);
  288.         OLED_WR_Byte(0x00,OLED_CMD);
  289.         
  290.         OLED_WR_Byte(0xd5,OLED_CMD);
  291.         OLED_WR_Byte(0xf0,OLED_CMD);
  292.         
  293.         OLED_WR_Byte(0xd9,OLED_CMD);
  294.         OLED_WR_Byte(0x22,OLED_CMD);
  295.         
  296.         OLED_WR_Byte(0xda,OLED_CMD);
  297.         OLED_WR_Byte(0x02,OLED_CMD);
  298.         
  299.         OLED_WR_Byte(0xdb,OLED_CMD);
  300.         OLED_WR_Byte(0x49,OLED_CMD);
  301.         
  302.         OLED_WR_Byte(0x8d,OLED_CMD);
  303.         OLED_WR_Byte(0x14,OLED_CMD);
  304.         
  305.         OLED_WR_Byte(0xaf,OLED_CMD);
  306.         OLED_Clear();
  307. }  


  308. /***************************************************************************************
  309.   * @实现效果        对24C02进行读写操作
  310. ***************************************************************************************/
  311. void main()
  312. {
  313. /************************************系统初始化****************************************/
  314.         CLKSWR = 0x51;                                                //选择内部高频RC为系统时钟,内部高频RC 2分频,Fosc =16MHz
  315.         CLKDIV = 0x01;                                                //Fosc 1分频得到Fcpu,Fcpu=16MHz
  316. /**********************************IIC配置初始化***************************************/
  317.         P0M1 = 0xC2;                                                //P01设置为推挽输出
  318.   P0M0 = 0xE6;                                                //P03设置为带上拉开漏输出
  319.         SCL_MAP = 0x01;                                                //SCL映射P01口
  320.         SDA_MAP = 0x00;                                                //SDA映射P00口
  321.         IICCON = 0x40;                                                 //启动IIC模块
  322.         OLED_Init();
  323.   fill_picture(0xff);
  324.   Delay_ms(300ul);
  325.         OLED_Clear();
  326.         
  327.         OLED_ShowCHinese(24,0,5);//
  328.         OLED_ShowCHinese(40,0,6);//
  329.         OLED_ShowCHinese(56,0,7);//
  330.         OLED_ShowCHinese(72,0,8);//
  331.         

  332.         OLED_ShowString(0,2,"Cjy_JDxy--21ic",16);  
  333.         while(1)
  334.         {
  335.                         
  336.         }
  337. }


效果图:
1.jpg
工程:
IIC-OLED.rar (70.16 KB, 下载次数: 26)
磨砂 发表于 2020-8-7 13:56 | 显示全部楼层
感谢楼主分享
晓伍 发表于 2020-8-7 13:58 | 显示全部楼层
是用io模拟的吗
八层楼 发表于 2020-8-7 14:00 | 显示全部楼层
稳定吗运行的
 楼主| 比神乐 发表于 2020-8-7 14:00 | 显示全部楼层
晓伍 发表于 2020-8-7 13:58
是用io模拟的吗

不是模拟,是硬件I2C
观海 发表于 2020-8-7 14:01 | 显示全部楼层
楼主辛苦了
 楼主| 比神乐 发表于 2020-8-7 14:02 | 显示全部楼层

比较稳定
您需要登录后才可以回帖 登录 | 注册

本版积分规则

470

主题

3537

帖子

7

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