|
关于OLED12864用IIC通讯显示受晶振频率影响解决方案
采用的单片机机STC8A8K64S4A12,同时STC15系列的也使用,测试过的
之前用软件模拟IIC驱动OLED12864时,当把单片机晶振频率调高时,OLED就不能正常显示了
后来找到了一些IIC程序,采用了一下,得以解决这一问题
问题还是IIC驱动程序没有写好,用卖家的例程也不行,还是的自己修改一下
此版程序,通过测试,就算把晶振调到27MHZ,也能正常显示
附件中有SPI通讯,软件模拟IIC,基于STC8A8K的硬件IIC,驱动OLED12864
不过STC8的硬件IIC通讯,还是受到晶振频率的影响,稍微修改了一下,比之前要好一点
贴出来的程序是单片机软件模拟IIC驱动OLED12864- #include "oled.h"
- #include "Font.h"
- #include "intrins.h"
- void Delay_OLED(u16 t)
- {
- u16 i,j;
- for(j=0;j<t;j++)
- {
- for(i=0;i<1;i++) //根据晶振频率调整延时
- {
- _nop_();
- //_nop_();_nop_();
- }
- }
- }
- /*********通过IIC写一字节数据******/
- void IIC_Write_Byte(u8 Byte)
- {
- u8 i;
- for(i=0;i<8;i++)
- {
- OLED_SDA = Byte &0X80; ////改变数据
- OLED_SCL = 1; //传输数据
- Delay_OLED(1);
- OLED_SCL = 0;
- Byte<<=1;
- Delay_OLED(1);
- }
- }
- /********起始信号*********/
- void IIC_Start()
- {
- OLED_SDA = 1;
- OLED_SCL = 1;
- Delay_OLED(1);
- OLED_SDA = 0;
- Delay_OLED(1);
- OLED_SCL = 0;
- Delay_OLED(1);
- }
- /********停止信号*********/
- void IIC_Stop()
- {
- OLED_SCL = 0;
- OLED_SDA = 0;
- Delay_OLED(1);
- OLED_SDA = 1;
- Delay_OLED(1);
- OLED_SCL = 1;
- Delay_OLED(1);
- }
- /*********ACK信号********/
- bit IIC_ACK()
- {
- u8 errtime=255;
- OLED_SCL = 0;
- OLED_SDA = 1; //释放总线
- Delay_OLED(1);
- OLED_SCL = 1;
- Delay_OLED(1);
- while(OLED_SDA) //读取 SDA上的电平,变为低电平,即有从机回复ACK信号
- {
- errtime--;
- if(!errtime) //超时退出
- {
- OLED_SCL=0;
- return 0;
- }
- }
- OLED_SCL=0;
- return 1;
- }
- /***********向SSD1306写一字节数据***********
- Dat:要写入的数据/命令
- Cmd:数据/命令标志 0,表示命令;1,表示数据;
- ********************************************/
- void Write_OLED_Byte(u8 Dat,u8 Cmd)
- {
- IIC_Start();
- IIC_Write_Byte(0X78);
- IIC_ACK();
- if(Cmd ==1) //数据
- IIC_Write_Byte(0X40);
- else //命令
- IIC_Write_Byte(0X00);
- IIC_ACK();
- IIC_Write_Byte(Dat);
- IIC_ACK();
- IIC_Stop();
- }
- /**********IIC_IO口初始化***********/
- void IIC_InitIO()
- {
- OLED_SDA = 1;
- OLED_SCL = 1;
- }
- //---------IIC 通讯----------------------------------------------------------
- /*********设置显示坐标*********/
- void OLED_Set_PoS(u8 page,u8 column)
- {
- Write_OLED_Byte(0XB0+page,OLED_CMD);
- Write_OLED_Byte( ((column&0XF0)>>4)|0X10,OLED_CMD);
- Write_OLED_Byte( column&0X0F,OLED_CMD);
- }
- ////开启OLED显示
- //void OLED_Display_On(void)
- //{
- // Write_OLED_Byte(0X8D,OLED_CMD); //SET DCDC命令
- // Write_OLED_Byte(0X14,OLED_CMD); //DCDC ON
- // Write_OLED_Byte(0XAF,OLED_CMD); //DISPLAY ON
- //}
- ////关闭OLED显示
- //void OLED_Display_Off(void)
- //{
- // Write_OLED_Byte(0X8D,OLED_CMD); //SET DCDC命令
- // Write_OLED_Byte(0X10,OLED_CMD); //DCDC OFF
- // Write_OLED_Byte(0XAE,OLED_CMD); //DISPLAY OFF
- //}
- /************操作整个屏幕************
- Input: Ins=0 清除整个屏幕
- Ins=0XFF 全部显示整个屏幕
- *************************************/
- void OLED_Screen_All(u8 Ins)
- {
- u8 page,seg;
- for(page=0;page<8;page++)
- {
- OLED_Set_PoS(page,0);
- for(seg=0;seg<128;seg++)
- {
- Write_OLED_Byte(Ins,OLED_DAT);
- Delay_OLED(1);
- }
- Delay_OLED(1);
- }
- }
- /*********OLED初始化***********/
- void OLED_Init()
- {
- Delay_OLED(2000);
-
- Write_OLED_Byte(0XD5,OLED_CMD); //晶振频率
- Write_OLED_Byte(0X80,OLED_CMD);
- Write_OLED_Byte(0XD9,OLED_CMD); //
- Write_OLED_Byte(0XF1,OLED_CMD);
- Write_OLED_Byte(0XDB,OLED_CMD); //
- Write_OLED_Byte(0X40,OLED_CMD);
- //--地址设置
- Write_OLED_Byte(0X20,OLED_CMD); //设置寻址模式
- Write_OLED_Byte(0X02,OLED_CMD); //0X00--水平寻址;0X01--垂直寻址;0X02--页面寻址
- //--硬件设置
- Write_OLED_Byte(0X40,OLED_CMD); //起始行
- Write_OLED_Byte(0XA8,OLED_CMD); //设置显示比列;
- Write_OLED_Byte(0X3F,OLED_CMD); //1/64
- Write_OLED_Byte(0XD3,OLED_CMD); //设置补偿
- Write_OLED_Byte(0X00,OLED_CMD);
- //显示方向-引脚向上为正方向
- Write_OLED_Byte(0XA1,OLED_CMD); //段寻址,add0-->seg0
- Write_OLED_Byte(0XC8,OLED_CMD); //com扫描方向,com0-com63
- //引脚在下为正方向
- //Write_OLED_Byte(0XA0,OLED_CMD); //段寻址,add127-->seg0
- //Write_OLED_Byte(0XC0,OLED_CMD); //com扫描方向,com63-com0
- Write_OLED_Byte(0X8D,OLED_CMD); //电荷泵设置
- Write_OLED_Byte(0X14,OLED_CMD); //REST=0X10, 0X14才能显示内容
- //--基本命令
- Write_OLED_Byte(0X81,OLED_CMD); //设置对比度
- Write_OLED_Byte(0XCF,OLED_CMD); //0X00-0XFF,与数值成正比 RES=0X7F
- Write_OLED_Byte(0XA4,OLED_CMD); //整体显示开启,可用来测试液晶是否显示正常
- //0XA4跟随RAM内容,0XA5不跟随RAM的内容,一直是白屏全部显示。
- Write_OLED_Byte(0XA6,OLED_CMD); //设置正显0XA6,反显0XA7
- Write_OLED_Byte(0XAF,OLED_CMD); //0XAE显示关,0XAF显示开
- Write_OLED_Byte(0X2E,OLED_CMD); //关闭滚屏
- //---清屏
- OLED_Screen_All(0);
- Delay_OLED(100);
- OLED_Screen_All(0XFF);
- Delay_OLED(2000);
- OLED_Screen_All(0);
- Delay_OLED(100);
- }
- ///***********垂直+水平滚屏***************/
- //void Ver_Lev_Screen()
- //{
- ////--垂直+水平滚屏-------------------------------------------------------------------
- // Write_OLED_Byte(0XA3,OLED_CMD); //设置垂直滚动区域
- // Write_OLED_Byte(0X10,OLED_CMD); //固定不动的行数,从顶部开始数
- // Write_OLED_Byte(0X20,OLED_CMD); //垂直滚动的行数,从固定行的下一行开始数
- //
- // Write_OLED_Byte(0X29,OLED_CMD); //垂直+右移///0X2A=垂直+左移
- // Write_OLED_Byte(0X00,OLED_CMD); //空字节
- // Write_OLED_Byte(0X06,OLED_CMD); //水平移动起始页
- // Write_OLED_Byte(0X05,OLED_CMD); //控制垂直+水平速率
- // Write_OLED_Byte(0X07,OLED_CMD); //水平移动结束页
- // Write_OLED_Byte(0X02,OLED_CMD); //垂直滚动偏移量,只控制垂直速率,=0只有水平移动
- // Write_OLED_Byte(0X2F,OLED_CMD); //启动滚屏
- ////---以上效果为,第一行为固定,第二三行垂直滚屏,第四行右移-------------------------
- //}
- /**************水平滚屏*****************/
- void Lev_Screen()
- {
- Write_OLED_Byte(0X26,OLED_CMD); //右移///0X27=左移
- Write_OLED_Byte(0X00,OLED_CMD); //空字节
- Write_OLED_Byte(0X06,OLED_CMD); //水平移动起始页
- Write_OLED_Byte(0X05,OLED_CMD); //控制垂直+水平速率
- Write_OLED_Byte(0X07,OLED_CMD); //水平移动结束页
- Write_OLED_Byte(0X00,OLED_CMD); //虚拟字节
- Write_OLED_Byte(0XFF,OLED_CMD); //虚拟字节
- Write_OLED_Byte(0X2F,OLED_CMD); //启动滚屏
- }
- ///**************清除N个8*16区域**********/
- //void Clear8X16(u8 page, u8 column ,u8 N)
- //{
- // u8 i,j,k;
- // for(k=0;k<N;k++)
- // {
- // for(i=0;i<2;i++)
- // {
- // OLED_Set_PoS(page+i,column+k*8);
- // for(j=8;j>0;j--)
- // Write_OLED_Byte(0X00,OLED_DAT);
- // }
- // }
- //}
- /*****************在(16行/2页)*Wide列区域写数据****************
- Input:
- *Buff@点阵数据 Num@字符个数,Wide@字体宽度
- Wide=8时,为写8*16的数据,字母,符号
- Wide=16时,为写宋体2号汉字
- **************************************************************/
- void Write_16xWide(u8 page,u8 column ,u8 *Buff,u8 Num,u8 Wide)
- {
- u8 i,j,k;
- for(k=0;k<Num;k++)
- {
- for(i=0;i<2;i++)
- {
- OLED_Set_PoS(page+i,column+k*8);
- for(j=Wide;j>0;j--)
- {
- Write_OLED_Byte(*Buff,OLED_DAT);
- Buff++;
- }
- }
- }
- }
- /**************写宋体12号汉字 16*Wide ***********
- Input: page@页 column@列 *CH@字符串
- 可以显示汉字,数字,字母,符号
- page:0 2 4 6 column:0~15
- ************************************************/
- void Write_GB16X16(u8 page,u8 column ,u8 *CH)
- {
- u8 a,k;
- if( (*CH>=0X20) && (*CH<=0X7E) ) column=column;
- else column*=8;
- while( *CH != '\0')
- {
- if( (*CH>=0X20) && (*CH<=0X7E) ) //数字,字母,符号 一行16个
- {
- k=*CH-0X20;
- for(a=0;a<2;a++)
- {
- Write_16xWide(page,column*8, &ASCII_8X16[k][0],1,8);
- }
- CH+=1;
- column+=1;
- }
- else //汉字,一行 8个
- {
- for(a=0;a<FontNum;a++)
- {
- if( (*CH == GB12Hanzi[a].Index[0]) && (*(CH+1)==GB12Hanzi[a].Index[1]) )
- Write_16xWide(page,column,&GB12Hanzi[a].Msk[0],1,16);
- }
- CH+=2;
- column+=16;
- }
- }
- }
- ///**************在8行/1页**6列的区域写字符***************
- //Input:
- // *CH@字符串 能写21个字符
- // page:0~7 column:0~20
- //*******************************************************/
- //void Write_GB6X8(u8 page,u8 column ,u8 *CH)
- //{
- // u8 j,k;
- // while( *CH != '\0')
- // {
- // if( (*CH>=0X20) && (*CH<=0X7E) ) //数字,字母,符号 一行16个
- // {
- // k=*CH-0X20;
- // OLED_Set_PoS(page,column*6);
- // for(j=0;j<6;j++)
- // Write_OLED_Byte(ASCII_6X8[k][j],OLED_DAT);
- // CH+=1;
- // column+=1;
- // }
- // }
- //}
复制代码
|
评分
-
查看全部评分
|