admin管理员组

文章数量:1570369

实验平台:CC2350
屏幕参数:128*64
驱动芯片: SSD1306

使用OLED时,想要重定向printf输出到OLED屏幕上,并实现横向128列输出完毕后或者遇到 ‘\n’ 时自动换行显示,并且将已输入内容向上移动一行,类似win的命令行窗口。实现的主要思路为SSD1306的设置显示偏移量( Set Display Offset (D3h) )

Set Display Offset (D3h)
This is a double byte command. The second command specifies the mapping of the display start line to one of COM0~COM63 (assuming that COM0 is the display start line then the display start line register is equal to 0).
For example, to move the COM16 towards the COM0 direction by 16 lines the 6-bit data in the second byte should be given as 010000b. To move in the opposite direction by 16 lines the 6-bit data should be given by 64 – 16, so the second byte would be 100000b. The following two tables (Table 10-1, Table 10-2) show the example of setting the command C0h/C8h and D3h.


基于这种办法,我们只要将偏移量移动字体的高度值,然后清空移动后行,指定新的输入点即可,比如我使用8*16的字体,那么我只要将偏移地址移动16即可,即从COM0移动到COM16,数值为从0x40到0x50。下面是我的实现办法,代码的适应性为0,后续继续改进。

  1. 实现偏移
uint8 OLED_VerticalScrolling(uint8 addr)
{
  //使用8*16字体
  if(addr >= 0x40 && addr < 0x50){  //第一行
    addr = 0x50; //切换到第二行开始
  }
  else if(addr >= 0x50 && addr < 0x60)//第二行
  {
    addr = 0x60; //切换到第三行开始
  }
  else if(addr >= 0x60 && addr < 0x70)//第三行
  {
    addr = 0x70; //切换到第四行开始
  }
  else{                                 //第四行
    addr = 0x40; //切换到第一行开始
  }
  OLED_WR_Byte(0xD3,OLED_CMD);        //设置起始位
  OLED_WR_Byte(addr,OLED_CMD);        //起始位移动16位
    
  return addr;
}
  1. 实现清空移动后的行
void OLED_ClearForPrintf(uint8 addr)
{
    unsigned char y,x; 
    unsigned char i,j;
    
  //使用8*16字体
  if(addr >= 0x40 && addr < 0x50){  //第一行
	i = 0;
	j =3;   
  }
  else if(addr >= 0x50 && addr < 0x60)//第二行
  {
	i = 2;
	j =4;    
  }
  else if(addr >= 0x60 && addr < 0x70)//第三行
  {
	i = 4;
	j =6;   
  }
  else{//第四行
  	i = 6;
	j =8; 
  }
  for(y=i;y<j;y++)
    {
        LCD_WrCmd(0xb0+y);
        LCD_WrCmd(0x01);
        LCD_WrCmd(0x10); 
        for(x=0;x<X_WIDTH;x++)
            LCD_WrDat(0);
    }    
}
  1. 重定向printf
__near_func int putchar(int c)//printf输出重定向
{
    static uint8_t x = 0, y = 0,state = 0;
    static uint8_t addr_next = 0x40;//默认第一行开始移动
    static uint8_t addr_now;
      
    if((x + 8 > 128) || c == '\n')    //换行 
    { 
      x = 0; 
      if(state ==1)
      {
        
          OLED_ClearForPrintf(addr_next);            //清除显示的最后一行
          addr_now = addr_next;                     //清除后成为当前编辑行
          addr_next = OLED_VerticalScrolling(addr_now); //垂直滚动2页,返回显示的最后一行的地址

          
          //使用8*16字体
          if(addr_now >= 0x40 && addr_now < 0x50){  //第一行
            y=0;
          }
          else if(addr_now >= 0x50 && addr_now < 0x60)//第二行
          {
            y=2;
          }
          else if(addr_now >= 0x60 && addr_now < 0x70)//第三行
          {
            y=4;
          }
          else{                                 //第四行
            y=6;
          }
        return c; 
      }
      else {
        y += 2;
        if(y > 4 ) 
          state = 1;
        return c;
      }
    }
    
    OLED_ShowChar(x, y, (uint8_t)c ,16);         //打印字符ch 
    x += 8;                                      //跳转到下一个位置, 是否越界有上面函数判断
    return c; 
}

本文标签: 换行oled