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

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

今天搞了一下OLED。
SDA:P2.6
SCL:P2.7.
模拟时序。
代码:
  1. #define        ALLOCATE_EXTERN
  2. #include "HC89F0541.h"
  3. #include "i2c_software.h"
  4. #include "oled.h"




  5. #define uchar unsigned char
  6. #define uint unsigned int
  7.         



  8. /***************************************************************************************
  9.   * @实现效果        对P00端口的消抖时间进行设置,251.9375us<消抖时间<255.9375us。
  10. ***************************************************************************************/
  11. void main()
  12. {
  13. /************************************系统初始化****************************************/
  14.         CLKSWR = 0x51;                                                //选择内部高频RC为系统时钟,内部高频RC 2分频,Fosc=16MHz
  15.         CLKDIV = 0x01;                                                //Fosc 1分频得到Fcpu,Fcpu=16MHz
  16. /**********************************端口消抖初始化**************************************/
  17.   P2M7 = 0xC0;                        //P27设置为推挽输出
  18.         P2M6 = 0xC0;                        //P26设置为推挽输出
  19.         
  20.         
  21.         OLED_Init();
  22.         OLED_Clear();
  23.         
  24.         OLED_ShowString(10,1,"I Love You!");// OLED TEST

  25.         while(1)
  26.         {
  27.                
  28.         }
  29. }
  1. #include "i2c_software.h"


  2. /*
  3.         [url=home.php?mod=space&uid=247401]@brief[/url]                        延迟1us
  4.         @param                        无
  5.         @retval                        无
  6. */
  7. static void delay(unsigned char num)
  8. {
  9.         
  10.         uchar i;
  11.         for(i=0;i<num;i++);
  12.         
  13. }


  14. /*
  15.         @brief                        ms延迟函数
  16.         @param                        无
  17.         @retval                        无
  18. */
  19. static void delay_ms(unsigned int ms)//延迟函数,MS级别
  20. {
  21.         unsigned int x,y;
  22.         for(x = ms;x>0;x--)
  23. {
  24.                 for(y = 12000;y>0;y--);
  25. }
  26. }


  27. /*
  28.         @brief                        初始化OLED与单片机的IO接口
  29.         @param                        无
  30.         @retval                        无
  31. */
  32. void OLED_GPIO_Init(void)
  33. {
  34.         
  35.         OLED_SCLK_Set();        //设PB6(SCL)为高电平
  36.         OLED_SDIN_Set();        //设PB7(SDA)为高电平
  37. }


  38. /*
  39.         @brief                        模拟IIC起始信号
  40.         @param                        无
  41.         @retval                        无
  42. */
  43. void OLED_IIC_Start(void)
  44. {

  45.         OLED_SCLK_Set();        //时钟线置高
  46.         OLED_SDIN_Set();        //信号线置高
  47.         delay(1);        //延迟1us
  48.         OLED_SDIN_Clr();        //信号线置低
  49.         delay(1);        //延迟1us
  50.         OLED_SCLK_Clr();        //时钟线置低
  51.         delay(1);        //延迟1us
  52. }


  53. /*
  54.         @brief                        模拟IIC停止信号
  55.         @param                        无
  56.         @retval                        无
  57. */
  58. void OLED_IIC_Stop(void)
  59. {
  60.         OLED_SDIN_Clr();        //信号线置低
  61.         delay(1);        //延迟1us
  62.         OLED_SCLK_Set();        //时钟线置高
  63.         delay(1);        //延迟1us
  64.         OLED_SDIN_Set();        //信号线置高
  65.         delay(1);        //延迟1us
  66. }


  67. /*
  68.         @brief                        模拟IIC读取从机应答信号
  69.         @param                        无
  70.         @retval                        无
  71. */
  72. static unsigned char IIC_Wait_Ack(void)
  73. {
  74.         unsigned char ack;

  75.         OLED_SCLK_Clr();        //时钟线置低
  76.         delay(1);        //延迟1us
  77.         OLED_SDIN_Set();        //信号线置高
  78.         delay(1);        //延迟1us
  79.         OLED_SCLK_Set();        //时钟线置高
  80.         delay(1);        //延迟1us
  81.         P2M6 = 0x62;                        //P26设置为上拉输入
  82.         delay(1);        //延迟1us
  83.         if(OLED_READ_SDIN())        //读取SDA的电平
  84.                 ack = IIC_NO_ACK;        //如果为1,则从机没有应答
  85.         else
  86.                 ack = IIC_ACK;                //如果为0,则从机应答
  87.         
  88.         OLED_SCLK_Clr();//时钟线置低
  89.         delay(1);        //延迟1us
  90.         P2M6 = 0xC0;                        //P27设置为推挽输出
  91.         delay(1);        //延迟1us
  92.         return ack;        //返回读取到的应答信息
  93. }




  94. /*
  95.         @brief                        IIC写入一个字节
  96.         @param                        IIC_Byte:写入的字节
  97.         @retval                        无
  98. */
  99. void Write_IIC_Byte(unsigned char IIC_Byte)
  100. {
  101.         unsigned char i;  //定义变量
  102.         for(i=0;i<8;i++) //for循环8次
  103.         {
  104.                 OLED_SCLK_Clr();        //时钟线置低,为传输数据做准备
  105.                 delay(1);        //延迟1us

  106.                 if(IIC_Byte & 0x80)        //读取最高位
  107.                           OLED_SDIN_Set();//最高位为1
  108.                 else
  109.                         OLED_SDIN_Clr();        //最高位为0

  110.                 IIC_Byte <<= 1;  //数据左移1位
  111.                 delay(1);        //延迟1us
  112.                 OLED_SCLK_Set(); //时钟线置高,产生上升沿,把数据发送出去
  113.                 delay(1);        //延迟1us
  114.         }
  115.         OLED_SCLK_Clr();        //时钟线置低
  116.         delay(1);        //延迟1us

  117.         while(IIC_Wait_Ack());        //从机应答
  118. }


  1. #include "oled.h"
  2. #include "oledfont.h"
  3. /*definition--------------------------------------------*/

  4. /*
  5.         @brief                        延迟1us
  6.         @param                        无
  7.         @retval                        无
  8. */
  9. static void delay(unsigned char num)
  10. {
  11.         
  12.         uchar i;
  13.         for(i=0;i<num;i++);
  14.         
  15. }


  16. /*
  17.         @brief                        ms延迟函数
  18.         @param                        无
  19.         @retval                        无
  20. */
  21. static void delay_ms(unsigned int ms)//延迟函数,MS级别
  22. {
  23.         unsigned int x,y;
  24.         for(x = ms;x>0;x--)
  25. {
  26.                 for(y = 12000;y>0;y--);
  27. }
  28. }

  29. /****************************以下为OLED应用层*******************************************/
  30. /*
  31.         @brief                        IIC写入命令
  32.         @param                        IIC_Command:写入的命令
  33.         @retval                        无
  34. */
  35. static void Write_IIC_Command(unsigned char IIC_Command)
  36. {
  37.         #if Software_IIC_EN
  38.         
  39.    OLED_IIC_Start();
  40.    Write_IIC_Byte(0x78);//写入从机地址,SD0 = 0
  41.    Write_IIC_Byte(0x00);//写入命令
  42.    Write_IIC_Byte(IIC_Command);//数据
  43.    OLED_IIC_Stop();  //发送停止信号
  44.         #else
  45.         I2C_GenerateSTART(I2C1,ENABLE);
  46.         I2C_Send_Byte(I2C1,0x78);
  47.         I2C_Send_Byte(I2C1,0x00);
  48.         I2C_Send_Byte(I2C1,IIC_Command);
  49.         I2C_GenerateSTOP(I2C1,ENABLE);
  50.         #endif
  51. }


  52. /*
  53.         @brief                        IIC写入数据
  54.         @param                        IIC_Data:数据
  55.         @retval                        无
  56. */
  57. static void Write_IIC_Data(unsigned char IIC_Data)
  58. {
  59.         #if Software_IIC_EN
  60.    OLED_IIC_Start();
  61.    Write_IIC_Byte(0x78);        //写入从机地址,SD0 = 0
  62.    Write_IIC_Byte(0x40);        //写入数据
  63.    Write_IIC_Byte(IIC_Data);//数据
  64.    OLED_IIC_Stop();                //发送停止信号
  65.         #else
  66.         I2C_GenerateSTART(I2C1,ENABLE);
  67.         I2C_Send_Byte(I2C1,0x78);
  68.         I2C_Send_Byte(I2C1,0x40);
  69.         I2C_Send_Byte(I2C1,IIC_Data);
  70.         I2C_GenerateSTOP(I2C1,ENABLE);
  71.         #endif
  72. }


  73. /*
  74.         @brief                        对OLED写入一个字节
  75.         @param                        dat:数据
  76.                                         cmd:1,写诶数据;0,写入命令
  77.         @retval                        无
  78. */
  79. void OLED_WR_Byte(unsigned char dat,unsigned char cmd)
  80. {
  81.         if(cmd)
  82.           {
  83.        Write_IIC_Data(dat); //写入数据
  84.           }
  85.         else {
  86.        Write_IIC_Command(dat); //写入命令
  87.         }
  88. }


  89. /*
  90.         @brief                        设置数据写入的起始行、列
  91.         @param                        x: 列的起始低地址与起始高地址;0x00~0x0f:设置起始列低地址(在页寻址模式);
  92.                                                 0x10~0x1f:设置起始列高地址(在页寻址模式)
  93.                                         y:起始页地址 0~7
  94.         @retval                        无
  95. */
  96. void OLED_Set_Pos(unsigned char x, unsigned char y)
  97. {
  98.         OLED_WR_Byte(0xb0+y,OLED_CMD);//写入页地址
  99.         OLED_WR_Byte((x&0x0f),OLED_CMD);  //写入列的地址  低半字节
  100.         OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);//写入列的地址 高半字节
  101. }                          


  102. /*
  103.         @brief                        开显示
  104.         @param                        无
  105.         @retval                        无
  106. */
  107. void OLED_Display_On(void)
  108. {
  109.         OLED_WR_Byte(0X8D,OLED_CMD);  //设置OLED电荷泵
  110.         OLED_WR_Byte(0X14,OLED_CMD);  //使能,开
  111.         OLED_WR_Byte(0XAF,OLED_CMD);  //开显示
  112. }


  113. /*
  114.         @brief                        关显示
  115.         @param                        无
  116.         @retval                        无
  117. */  
  118. void OLED_Display_Off(void)
  119. {
  120.         OLED_WR_Byte(0XAE,OLED_CMD);  //关显示
  121.         OLED_WR_Byte(0X8D,OLED_CMD);  //设置OLED电荷泵
  122.         OLED_WR_Byte(0X10,OLED_CMD);  //失能,关
  123. }                                            


  124. /*
  125.         @brief                        清屏
  126.         @param                        无
  127.         @retval                        无
  128. */         
  129. void OLED_Clear(void)  
  130. {  
  131.         unsigned char i,n;                    //定义变量
  132.         for(i=0;i<8;i++)  
  133.         {  
  134.                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //从0~7页依次写入
  135.                 OLED_WR_Byte (0x00,OLED_CMD);      //列低地址
  136.                 OLED_WR_Byte (0x10,OLED_CMD);      //列高地址  
  137.                 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); //写入 0 清屏
  138.         }
  139. }


  140. /*
  141.         @brief                        显示一个字符
  142.         @param                        x:起始列
  143.                                         y:起始页,SIZE = 16占两页;SIZE = 12占1页
  144.                                         chr:字符
  145.         @retval                        无
  146. */
  147. void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr)
  148. {              
  149.         unsigned char c=0,i=0;        
  150.                 c=chr-' '; //获取字符的偏移量        
  151.                 if(x>Max_Column-1){x=0;y=y+2;} //如果列数超出了范围,就从下2页的第0列开始

  152.                
  153.                 OLED_Set_Pos(x,y);        //从x y 开始画点
  154.                 for(i=0;i<8;i++)  //循环8次 占8列
  155.                 OLED_WR_Byte(F8X16[c*16+i],OLED_DATA); //找出字符 c 的数组位置,先在第一页把列画完
  156.                 OLED_Set_Pos(x,y+1); //页数加1
  157.                 for(i=0;i<8;i++)  //循环8次
  158.                 OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA); //把第二页的列数画完
  159.                
  160.                
  161. }


  162. /*
  163.         @brief                        计算m^n
  164.         @param                        m:输入的一个数
  165.                                         n:输入数的次方
  166.         @retval                        result:一个数的n次方
  167. */
  168. unsigned int oled_pow(unsigned char m,unsigned char n)
  169. {
  170.         unsigned int result=1;         
  171.         while(n--)result*=m;   
  172.         return result;
  173. }                                 


  174. /*
  175.         @brief                        在指定的位置,显示一个指定长度大小的数
  176.         @param                        x:起始列
  177.                                         y:起始页
  178.                                         num:数字
  179.                                         len:数字的长度
  180.                                         size:显示数字的大小
  181.         @retval                        无
  182. */                  
  183. void OLED_ShowNum(unsigned char x,unsigned char y,unsigned int num,unsigned char len,unsigned char size)
  184. {                 
  185.         unsigned char t,temp;  //定义变量
  186.         unsigned char enshow=0;                //定义变量

  187.         for(t=0;t<len;t++)
  188.         {
  189.                 temp=(num/oled_pow(10,len-t-1))%10;//取出输入数的每个位,由高到低
  190.                 if(enshow==0&&t<(len-1)) //enshow:是否为第一个数;t<(len-1):判断是否为最后一个数
  191.                 {
  192.                         if(temp==0) //如果该数为0
  193.                         {
  194.                                 OLED_ShowChar(x+(size/2)*t,y,' ');//显示 0 ;x+(size2/2)*t根据字体大小偏移的列数(8)
  195.                                 continue; //跳过剩下语句,继续重复循环(避免重复显示)
  196.                         }else enshow=1;
  197.                 }
  198.                  OLED_ShowChar(x+(size/2)*t,y,temp+'0'); //显示一个位;x+(size2/2)*t根据字体大小偏移的列数(8)
  199.         }
  200. }


  201. /*
  202.         @brief                        显示字符串
  203.         @param                        x:起始列
  204.                                         y:起始页
  205.                                         *chr:第一个字符首地址
  206.         @retval                        无
  207. */
  208. void OLED_ShowString(unsigned char x,unsigned char y,unsigned char *chr)
  209. {
  210.         unsigned char j=0; //定义变量

  211.         while (chr[j]!='\0') //如果不是最后一个字符
  212.         {               
  213.                 OLED_ShowChar(x,y,chr[j]); //显示字符
  214.                 x+=8; //列数加8 ,一个字符的列数占8
  215.                 if(x>=128){x=0;y+=2;} //如果x大于等于128,切换页,从该页的第一列显示
  216.                 j++; //下一个字符
  217.         }
  218. }






  219. /*
  220.         @brief                        OLED初始化函数
  221.         @param                        无
  222.         @retval                        无
  223. */                                    
  224. void OLED_Init(void)
  225. {
  226.         #if Software_IIC_EN
  227.         OLED_GPIO_Init();        //GPIO口初始化,软件i2c
  228.         #else
  229.         I2CInitMasterMode();
  230.         #endif
  231.         delay_ms(200);        //延迟,由于单片机上电初始化比OLED快,所以必须加上延迟,等待OLED上复位完成

  232.         OLED_WR_Byte(0xAE,OLED_CMD);        //关闭显示

  233.         OLED_WR_Byte(0x00,OLED_CMD);        //设置低列地址
  234.         OLED_WR_Byte(0x10,OLED_CMD);        //设置高列地址
  235.         OLED_WR_Byte(0x40,OLED_CMD);        //设置起始行地址
  236.         OLED_WR_Byte(0xB0,OLED_CMD);        //设置页地址

  237.         OLED_WR_Byte(0x81,OLED_CMD);         // 对比度设置,可设置亮度
  238.         OLED_WR_Byte(0xFF,OLED_CMD);        //  265  

  239.         OLED_WR_Byte(0xA1,OLED_CMD);        //设置段(SEG)的起始映射地址;column的127地址是SEG0的地址
  240.         OLED_WR_Byte(0xA6,OLED_CMD);        //正常显示;0xa7逆显示

  241.         OLED_WR_Byte(0xA8,OLED_CMD);        //设置驱动路数(16~64)
  242.         OLED_WR_Byte(0x3F,OLED_CMD);        //64duty
  243.         
  244.         OLED_WR_Byte(0xC8,OLED_CMD);        //重映射模式,COM[N-1]~COM0扫描

  245.         OLED_WR_Byte(0xD3,OLED_CMD);        //设置显示偏移
  246.         OLED_WR_Byte(0x00,OLED_CMD);        //无偏移
  247.         
  248.         OLED_WR_Byte(0xD5,OLED_CMD);        //设置震荡器分频
  249.         OLED_WR_Byte(0x80,OLED_CMD);        //使用默认值
  250.         
  251.         OLED_WR_Byte(0xD9,OLED_CMD);        //设置 Pre-Charge Period
  252.         OLED_WR_Byte(0xF1,OLED_CMD);        //使用官方推荐值
  253.         
  254.         OLED_WR_Byte(0xDA,OLED_CMD);        //设置 com pin configuartion
  255.         OLED_WR_Byte(0x12,OLED_CMD);        //使用默认值
  256.         
  257.         OLED_WR_Byte(0xDB,OLED_CMD);        //设置 Vcomh,可调节亮度(默认)
  258.         OLED_WR_Byte(0x40,OLED_CMD);        ////使用官方推荐值
  259.         
  260.         OLED_WR_Byte(0x8D,OLED_CMD);        //设置OLED电荷泵
  261.         OLED_WR_Byte(0x14,OLED_CMD);        //开显示
  262.         
  263.         OLED_WR_Byte(0xAF,OLED_CMD);        //开启OLED面板显示
  264.         OLED_Clear();        //清屏
  265.         OLED_Set_Pos(0,0);          //设置数据写入的起始行、列
  266. }  


  267. /*
  268.         @brief                        OLED滚屏函数,范围0~1页,水平向左
  269.         @param                        无
  270.         @retval                        无
  271. */        
  272. void OLED_Scroll(void)
  273. {
  274.         OLED_WR_Byte(0x2E,OLED_CMD);        //关闭滚动
  275.         OLED_WR_Byte(0x27,OLED_CMD);        //水平向左滚动
  276.         OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
  277.         OLED_WR_Byte(0x00,OLED_CMD);        //起始页 0
  278.         OLED_WR_Byte(0x00,OLED_CMD);        //滚动时间间隔
  279.         OLED_WR_Byte(0x01,OLED_CMD);        //终止页 1
  280.         OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
  281.         OLED_WR_Byte(0xFF,OLED_CMD);        //虚拟字节
  282.         OLED_WR_Byte(0x2F,OLED_CMD);        //开启滚动
  283. }

效果图:
1.jpg
工程:
OLED.rar (89.41 KB, 下载次数: 18)
木木guainv 发表于 2020-8-7 13:55 | 显示全部楼层
代码很详细
磨砂 发表于 2020-8-7 13:56 | 显示全部楼层
感谢楼主分享
晓伍 发表于 2020-8-7 13:57 | 显示全部楼层
真的好厉害
八层楼 发表于 2020-8-7 13:59 | 显示全部楼层
iic的接口吗?
观海 发表于 2020-8-7 14:01 | 显示全部楼层
非常值得参考
 楼主| 比神乐 发表于 2020-8-7 14:03 | 显示全部楼层

是的。
帅气的菜鸟 发表于 2020-8-7 14:58 | 显示全部楼层
不知道为什么,被板子后面的书吸引了眼球
 楼主| 比神乐 发表于 2020-8-7 15:01 | 显示全部楼层
帅气的菜鸟 发表于 2020-8-7 14:58
不知道为什么,被板子后面的书吸引了眼球

那是康辉写的《平均分》
您需要登录后才可以回帖 登录 | 注册

本版积分规则

470

主题

3535

帖子

7

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