经过长时间的尝试,下载功能终于又恢复了,起初以为是下载器过于脆弱,现在终于明白所配的杜邦线才是真正的元凶,4根线中为独黄线出现了断线,如果按序使用的话无论你怎么连也无法跳开异常。恢复了下载功能,就先从OLED屏的显示驱动入手开始测试。
为了减少失败的风险,所选的OLED屏是一款0.96寸的准双色屏,其显示分辨率为128*64像素点。该显示屏以I2C的接口方式工作,可以GPIO来模拟I2C来驱动它。
为节省资源,这里直接使用的LED1和LED2所使用的引脚,只需打开LED与相关引脚的连接即可。
OLED屏与开发板的具体连接关系为:
SCL--- PB4
SDA---PB4
为输出高低电平,所进行的定义为:
#defineSCL_highgpio_set_level(GPIO_PB4,1)
#defineSCL_lowgpio_set_level(GPIO_PB4,0)
#defineSDA_highgpio_set_level(GPIO_PB5,1)
#defineSDA_lowgpio_set_level(GPIO_PB5,0)
由于MCU的处理速度较高,为此在输出高低电平时需添加适当的延时,否则将无法使OLED屏工作。以I2C的开始与结束函数为例,其内容如下:
voidIIC_Start()
  • {
  •       SCL_high;
  •       delay_us(2);
  •       SDA_high;
  •       delay_us(2);
  •       SDA_low;
  •       delay_us(2);
  •       SCL_low;
  •       delay_us(2);
  • }
  • voidIIC_Stop()
  • {
  •       SCL_low;
  •       delay_us(2);
  •       SDA_low;
  •       delay_us(2);
  •       SCL_high;
  •       delay_us(2);
  •       SDA_high;
  •       delay_us(2);
  • }
  • 复制代码
    以模拟方式实现I2C发送字节数据的函数为:
    void Write_IIC_Byte(unsignedcharIIC_Byte)
  • {
  •     unsignedchari;
  •     unsignedcharm,da;
  •     da=IIC_Byte;
  •     SCL_low;
  •     for(i=0;i<8;i++)
  •     {
  •         m=da;
  •         m=m&0x80;
  •         if(m==0x80)
  •         {
  •             SDA_high;
  •         }
  •         elseSDA_low;
  •         da=da<<1;
  •         delay_us(2);
  •         SCL_high;
  •         delay_us(2);
  •         SCL_low;
  •         delay_us(2);
  •      }
  • }
  • 复制代码
    OLED屏的初始化函数为:
    voidOLED_Init(void)
  • {
  •       OLED_WR_Byte(0xAE,OLED_CMD);
  •       OLED_WR_Byte(0x02,OLED_CMD);
  •       OLED_WR_Byte(0x10,OLED_CMD);
  •       OLED_WR_Byte(0x40,OLED_CMD);
  •       OLED_WR_Byte(0x81,OLED_CMD);
  •       OLED_WR_Byte(0xff,OLED_CMD);
  •       OLED_WR_Byte(0xA1,OLED_CMD);
  •       OLED_WR_Byte(0xC8,OLED_CMD);
  •       OLED_WR_Byte(0xA6,OLED_CMD);
  •       OLED_WR_Byte(0xA8,OLED_CMD);
  •       OLED_WR_Byte(0x3f,OLED_CMD);
  •       OLED_WR_Byte(0xD3,OLED_CMD);
  •       OLED_WR_Byte(0x00,OLED_CMD);
  •       OLED_WR_Byte(0xd5,OLED_CMD);
  •       OLED_WR_Byte(0x80,OLED_CMD);
  •       OLED_WR_Byte(0xD9,OLED_CMD);
  •       OLED_WR_Byte(0xF1,OLED_CMD);
  •       OLED_WR_Byte(0xDA,OLED_CMD);
  •       OLED_WR_Byte(0x12,OLED_CMD);
  •       OLED_WR_Byte(0xDB,OLED_CMD);
  •       OLED_WR_Byte(0x40,OLED_CMD);
  •       OLED_WR_Byte(0x20,OLED_CMD);
  •       OLED_WR_Byte(0x02,OLED_CMD);
  •       OLED_WR_Byte(0x8D,OLED_CMD);
  •       OLED_WR_Byte(0x14,OLED_CMD);
  •       OLED_WR_Byte(0xA4,OLED_CMD);
  •       OLED_WR_Byte(0xA6,OLED_CMD);
  •       OLED_WR_Byte(0xAF,OLED_CMD);
  •       OLED_WR_Byte(0xAF,OLED_CMD);
  •       OLED_Clear();
  •       OLED_Set_Pos(0,0);
  • }
  • 复制代码
    实现OLED屏清除效果的函数为:
    void OLED_Clear(void)
  • {
  •         unsignedchari,n;
  •     for(i=0;i<8;i++)
  •     {
  •         OLED_WR_Byte (0xb0+i,OLED_CMD);
  •         OLED_WR_Byte (0x00,OLED_CMD);
  •         OLED_WR_Byte (0x10,OLED_CMD);
  •         for(n=0;n<128;n++) OLED_WR_Byte(0x00,OLED_DATA);
  •     }
  • }
  • 复制代码
    在字库的配合下,实现字符显示的函数为:
    voidOLED_ShowChar(unsignedcharx,unsignedchary,unsignedcharchr,unsignedcharChar_Size)
  • {
  •      unsignedchar c=0,i=0;
  •      c=chr-' ';
  •      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);
  •       }
  • }
  • 复制代码
    实现数值显示的函数为:
    voidOLED_ShowNum(unsignedcharx,unsignedchary,longintnum,unsignedcharlen,unsignedchar size2)
  • {
  •         unsignedchart,temp;
  •         unsignedcharenshow=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;
  •             }
  •             elseenshow=1;
  •         }
  •         OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
  •     }
  • }
  • 复制代码
    比较令人差异的是移植字符串显示函数时,却一直无法完成编译,问题一直定位在指针变量上,难道Telink B91或其开发工具不支持该数据类型?没办法,在用到字符串显示时只好靠字符来码了!当然,还有一种方法就是以数组来替代指针的使用。实现测试效果的主程序为:
    intmain (void)
  • {
  •         sys_init(LDO_1P4_LDO_1P8, VBAT_MAX_VALUE_GREATER_THAN_3V6);
  •         user_read_flash_value_calib();
  •         CCLK_24M_HCLK_24M_PCLK_24M;
  •         user_init();
  •         OLED_Init();
  •     OLED_Clear();
  •     OLED_ShowChar(20,0,'T',16);
  •     OLED_ShowChar(28,0,'e',16);
  •     OLED_ShowChar(36,0,'l',16);
  •     OLED_ShowChar(44,0,'i',16);
  •     OLED_ShowChar(52,0,'n',16);
  •     OLED_ShowChar(60,0,'k',16);
  •     OLED_ShowChar(76,0,'B',16);
  •     OLED_ShowNum(84,0,91,2,16);
  •         OLED_ShowCHinese(20,2,3);
  •         OLED_ShowCHinese(36,2,4);
  •         OLED_ShowCHinese(52,2,5);
  •         while (1) {
  •                 delay_ms(1000);
  •                 gpio_toggle(LED3);
  •                 gpio_toggle(LED4);
  •         }
  •         return 0;
  • }
  • 复制代码
    image.png
    OLED屏显示效果图