这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【EFM8BB52】脑电小车—oled我终于点亮了(二)

共8条 1/1 1 跳转至

【EFM8BB52】脑电小车—oled我终于点亮了(二)

工程师
2022-01-03 15:38:58     打赏

熟悉了几天编译器,通过参考学长的代码,终于把四阵IIC的OLED点亮了。

IIC,即I²C,全称 Inter-Integrated Circuit,字面上的意思是集成电路之间,它其实是I²C Bus简称,所以中文应该叫 集成电路总线 ,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。(百度百科)

简单地说,IIC就是一种通信协议,是为了能让主板,或嵌入式系统等与其他外设模块进行通信而进行开发的。玩过stm32开发板的同学都知道,对于一块stm32核心开发板而言,要想使用其他的外设模块,就肯定要经过接线,写代码,烧录运行的这个过程。其实这个过程,就是一个stm32与外设模块通信的过程。接线,就是搭建通信的线路。写代码,就是制定通信的传输协议。烧录运行,就是正式的通信过程。只不过有的模块通信过程很简单,大家感觉不出来。外设和芯片间的通信可以形象地比喻成两个人讲话:i、你说的别人得能听懂:双方约定信号的协议。ii、你的语速别人得能接受:双方满足时序要求。但是随着科技的发展,模块越来越多,总不可能,每个模块都要制定一种通信协议,这样不现实。所以,总要有一些代表性的协议能够适应大部分的模块的通信。IIC这是这样一种协议,一个IIC总线上,可以挂载多个外接设备。IIC总线上的信息传送是根据SCL时钟信号,每一次数据为的发送都发生在一个单独的SCl时钟周期内。

IC协议的通信过程:要搭建IIC的通信线路,出除去电源之外,还需要两条线,分别是SDA和SCLK

SDA:数据信号线,用于传输数据

SCLK:时钟信号线,用于产生时钟频率,控制时序,实现协议过程

由此可以看出,由于是单总线进行数据传输,所以IIC协议是半双工的。

1354072277_3118.jpg

 void IIC_Start()
 {
   OLED_SCLK_Set() ;
   NOP();NOP();NOP();     //等待延时
   OLED_SDIN_Set();
   NOP();NOP();NOP();       //等待延时
   OLED_SDIN_Clr();
   NOP();NOP();NOP();      //等待延时
   OLED_SCLK_Clr();
   NOP();NOP();NOP();      //等待延时
 }
 void IIC_Stop()
 {
    OLED_SCLK_Set() ;
    NOP();NOP();NOP();    //等待延时
    OLED_SDIN_Clr();
    NOP();NOP();NOP();    //等待延时
    OLED_SDIN_Set();
    NOP();NOP();NOP();    //等待延时
 }

数据传输和响应信号

数据传输:SDA上的数据只能在SCL为低电平期间翻转变化,在SCL为高电平期间必须保持稳定,IIC设备只在SCL为高电平期间采集SDA数据。 响应信号(ACK):单片机发完8bit数据后就不再驱动总线了(SDA引脚变输入),而SDA和SDL硬件设计时都有上拉电阻,所以这时候SDA变成高电平。那么在第8个数据位,如果外接IIC设备能收到信号的话接着在第9个周期把SDA拉低,那么处理器检测到SDA拉低就能知道外接IIC设备数据已经收到。IIC数据从最高位开始传输(小端传输)。

1354072784_8181.jpg

 void IIC_Wait_Ack()
 {
    OLED_SCLK_Set() ;
    NOP();NOP();NOP();
    OLED_SCLK_Clr();
    NOP();NOP();NOP();
 }
 
 void Write_IIC_Byte(unsigned char IIC_Byte)
 {
     unsigned char i;
     unsigned char m,da;
     da=IIC_Byte;
     NOP();NOP();NOP();
     OLED_SCLK_Clr();
     NOP();NOP();NOP();
     for(i=0;i<8;i++)
     {
         m=da;
         OLED_SCLK_Clr();
         m=m&0x80;
         if(m==0x80)
         {OLED_SDIN_Set();}
         else OLED_SDIN_Clr();
         NOP();NOP();NOP();
         da=da<<1;
         OLED_SCLK_Set();
         NOP();NOP();NOP();
         OLED_SCLK_Clr();
         NOP();NOP();NOP();
       }
 }
 /**
  * @name:Write_IIC_Command(unsigned char IIC_Command)
  * @msg: IIC写一个命令
  * @param {unsigned char} IIC_Command
  * @return {*}
  */
 void Write_IIC_Command(unsigned char IIC_Command)
 {
     IIC_Start();
     Write_IIC_Byte(0x78);
     IIC_Wait_Ack();
     Write_IIC_Byte(0x00);
     IIC_Wait_Ack();
     Write_IIC_Byte(IIC_Command);
     IIC_Wait_Ack();
     IIC_Stop();
 }
 /**
  * @name: Write_IIC_Data(unsigned char IIC_Data)
  * @msg:  IIC写一个数据
  * @param {unsigned char} IIC_Data
  * @return {*}
  */
 void Write_IIC_Data(unsigned char IIC_Data)
 {
     IIC_Start();
     Write_IIC_Byte(0x78);     //D/C#=0; R/W#=0
     IIC_Wait_Ack();
     Write_IIC_Byte(0x40);     //write data
     IIC_Wait_Ack();
     Write_IIC_Byte(IIC_Data);
     IIC_Wait_Ack();
     IIC_Stop();
 }
 /**
  * @name: OLED_WR_Byte(unsigned dat,unsigned cmd)
  * @msg:  OLED写一个字节
  * @param {unsigned} dat 写数据
  * @param {unsigned} cmd 写命令
  * @return {*}
  */
 void OLED_WR_Byte(unsigned dat,unsigned cmd)
 {
     if(cmd)
     {
         Write_IIC_Data(dat);
     }
     else
     {
         Write_IIC_Command(dat);
     }
 }
 
 void OLED_Display_Off(void)
 {
   OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
   OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
   OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
 }
 
 void OLED_Clear(void)
 {
   u8 i,n;
   for(i=0;i<8;i++)
   {
       OLED_WR_Byte (0xb0+i,OLED_CMD);              //设置页地址(0~7)
       OLED_WR_Byte (0x00,OLED_CMD);                //设置显示位置—列低地址
       OLED_WR_Byte (0x10,OLED_CMD);                //设置显示位置—列高地址
       for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); //更新显示
   }
 }
 void OLED_On(void)
 {
   u8 i,n;
   for(i=0;i<8;i++)
   {
       OLED_WR_Byte (0xb0+i,OLED_CMD);              //设置页地址(0~7)
       OLED_WR_Byte (0x00,OLED_CMD);                //设置显示位置—列低地址
       OLED_WR_Byte (0x10,OLED_CMD);                //设置显示位置—列高地址
       for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); //更新显示
   }
 }
 void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
 {
       unsigned char c=0,i=0;
       c=chr-' ';//得到偏移后的值
       if(x>Max_Column-1){x=0;y=y+2;}
       if(Char_Size ==16)
         {
         OLED_Set_Pos(x,y);
         for(i=0;i<8;i++)
         OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
         OLED_Set_Pos(x,y+1);
         for(i=0;i<8;i++)
         OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
         }
         else {
           OLED_Set_Pos(x,y);
           for(i=0;i<6;i++)
           OLED_WR_Byte(F6x8[c][i],OLED_DATA);
         }
 }
 void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
 {
     u8 t,temp;
     u8 enshow=0;
     for(t=0;t<len;t++)
     {
         temp=(num/oled_pow(10,len-t-1))%10;
         if(enshow==0&&t<(len-1))
         {
           if(temp==0)
           {
             OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
             continue;
           }else enshow=1;
         }
         OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
     }
 }
 







关键词: EFM8BB52     小夜灯     OLED    

专家
2022-01-03 16:04:25     打赏
2楼

谢谢分享


专家
2022-01-03 16:55:03     打赏
3楼

谢谢分享


高工
2022-01-03 20:33:02     打赏
4楼

这样看来,难度似乎也不是太大啊


工程师
2022-01-04 00:05:52     打赏
5楼

马上过来学习


专家
2022-01-04 00:53:39     打赏
6楼

学学


工程师
2022-01-04 08:50:00     打赏
7楼

学习了,感谢楼主分享。


高工
2022-01-04 10:00:15     打赏
8楼

看看


共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]