lxj19901115的个人空间 https://bbs.21ic.com/?754113 [收藏] [复制] [RSS]

日志

关于OLEDSSD1306的滚动显示

已有 748 次阅读2015-1-14 11:50 |个人分类:备份|系统分类:单片机| active, scroll, 控制器, 局限性, speed

在SSD1306控制器内部有滚动显示的控制命令,
以向右滚动显示为例,命令如下
      OLED_SD1306_WriteCmd(0x26);//r
      OLED_SD1306_WriteCmd(0x00);//duty
      OLED_SD1306_WriteCmd(0x04);//start page
      OLED_SD1306_WriteCmd(0x07); //speed     
      OLED_SD1306_WriteCmd(0x05);//end page
      OLED_SD1306_WriteCmd(0x01);//scroll timers
      OLED_SD1306_WriteCmd(0x00); //duty     
      OLED_SD1306_WriteCmd(0xff);//duty
      OLED_SD1306_WriteCmd(0x2f);//active
使用内部控制命令的局限性有,步伐不好控制,还有就是对于滚动显示的内容不能很好实时的更新,比如
图片A滚动显示之后接着图片B接着滚动显示,而是用内部控制命令的话,对于在A图片显示完毕之后衔接B的图片的时机非常不好把握,
所以针对多个图片的衔接滚动显示,我的解决方法如下:
首先为要滚动显示的图片建立文件ID,如下
#define                c_idx_16x10_ascii_v                                4       
#define                c_idx_16x10_ascii_w                                5       
#define                c_idx_16x10_digit_0                                6       
#define                c_idx_16x10_digit_1                                7       
#define                c_idx_16x10_digit_2                                8       
#define                c_idx_16x10_digit_3                                9       
#define                c_idx_16x10_digit_4                                10       
#define                c_idx_16x10_digit_5                                11       
#define                c_idx_16x10_digit_6                                12       
#define                c_idx_16x10_digit_7                                13       
#define                c_idx_16x10_digit_8                                14       
#define                c_idx_16x10_digit_9                                15       
#define                c_idx_16x10_dir_p                                16
对要显示的图片建立所以值,在建立索引值之后,可以根据各图片的ID,建立成滚动列表
const u16 T_MuneMainBmpIdxInfo2[][2]= //此处为主菜单需要显示警告信息的时候列表
{
  
  {c_idx_null},
  
  {c_idx_16x24_MenuMain_0,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_1,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_2,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_3,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_4,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_5,c_idx_16x12_Menu_Drop},
  {c_idx_10x20_menu_warrning,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_0,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_1,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_2,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_3,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_4,c_idx_16x12_Menu_Drop},
  {c_idx_16x24_MenuMain_5,c_idx_16x12_Menu_Drop},
  {c_idx_10x20_menu_warrning},
  {c_idx_null},  

};
在建立好图片ID表格之后,还需要建立另外一个表格,该表格用于存储,在显示该图片的时候,存储该图片的大小,
该大小为X或者Y的尺寸,,至于是X还是Y,主要是取决于取模方式,
该表格如下,
const u8 T_MuneMainBmpIdxInfo2_Size[]=
{
64,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
c_16x12_menu_drop_x_size,
c_16x24_menumain_x_size,
32,
c_ListEnd,
};
好了,在建立完这两张表格之后,那么就可以根据这两张表格来滚动显示该组合的图片了,
定义:g_scroll_add_inc 该变量用于滚动的累加器,


具体方法如下:
首先根据 g_scroll_add_inc 根据此变量,算出,第一个要显示的图片的尺寸和第一个图片的ID

u8 gui_menu_waits_scroll_get_files(void)
{
    u16 px_add;
    u16 *p_list = (u16*)&T_MenuScrollWaitsList[0][0];//指向表格
    u16 p_data;//真实数据
    u8 p_bmp_size;//算出的图片大小
    u16 list_idx,list_offset;//临时变量
    px_add = c_OLED_X_POS_Max;//当调用该函数的时候,说明表格0这个位置的数据已经显示完毕
    list_idx = 1;
    list_offset = 0;
    p_bmp_size = 0;
    while(1)
    {
        p_data = *(p_list+list_idx*c_list_waits_size+list_offset);//得出链表中的数据
        if(p_data == c_null_info)//判断元素是否为空数据
        {
             list_idx++;
             list_offset = 0;
             continue;     
        }
        p_bmp_size = gui_get_files_x_size(p_data);//根据获得的索引值,算出图片大小
        px_add+=p_bmp_size;
        if(g_scroll_add_inc == px_add)//如果偏移量相等,说明p_data 这个数据里面的索引值的图片已经不用显示,所以要指到下个图片
        {
            
            list_offset++;
            if(list_offset >(c_list_waits_size-1))
            {
                list_offset = 0;
                list_idx++;
            }
            g_scroll_waits_idx = list_idx;
            g_scroll_waits_offset = list_offset;
            return 0;
        }
        else if(g_scroll_add_inc < px_add)//偏移量不相同,并且小的话,说明,说明p_data这个里面的图片是需要显示的
        {
            g_scroll_waits_idx = list_idx;
            g_scroll_waits_offset = list_offset;         
            return (p_bmp_size-(px_add-g_scroll_add_inc));
        }
        list_offset++;//这里面操作隐含的条件是 g_scroll_add_inc 大于 px_add,所以继续偏移
        if(list_offset > (c_list_waits_size-1))
        {
            list_offset = 0;
            list_idx++;
        }
    }
   
}
此函数的作用有这几点,第一根据 g_scroll_add_inc 算出第一个要显示的图片ID编号,
第二同时结合g_scroll_add_inc和该ID所对应的图片尺寸算出,第一张图片的显示范围
比如算出的ID是 16x24_xxx,那么该图片的X尺寸是24个点,那么范围就是要显示的
x_start ~24,该x_start 范围在0-24之间,
在算出和装载第一个图片的内容到内存之后,那么接下来就要计算接下来的图片,
接下来的图片,根据OLED的尺寸,以32X64的OLED为例,那么第二个图片肯定是一个完整的图片,,,
然后一直到最后一个图片,最后一个图片同样的有可能是显示一部分,有可能是全部显示出来,
而这个显示的一部分,则是显示该图片的后部分,,
具体参考代码如下
void gui_menu_waits_scroll(void)
{
    u16 *p_List;
    u8 x_pos;
    u16 pdata;
    u8 bmpsize;
    u8 load_x_pos_start;
    u8 load_x_pos_size;
    x_pos = 0;
        gui_buffer_ClearRam();
    p_List = (u16*)&T_MenuScrollWaitsList[0][0];        
        if(g_scroll_add_inc < c_OLED_X_POS_Max)
        {
                x_pos = gui_loadpic_to_ram(x_pos,0,c_idx_null,0,c_OLED_X_POS_Max-g_scroll_add_inc);
        g_scroll_waits_idx = 1;
        g_scroll_waits_offset = 0;                
        }
        else
        {       
                load_x_pos_start = gui_menu_waits_scroll_get_files();
        pdata = *(p_List+g_scroll_waits_idx*c_list_waits_size+g_scroll_waits_offset);
        load_x_pos_size = gui_get_files_x_size(pdata);
        x_pos = gui_loadpic_to_ram(x_pos,0,pdata,load_x_pos_start,load_x_pos_size);
        g_scroll_waits_offset++;
        if(g_scroll_waits_offset > (c_list_waits_size-1))
        {
             g_scroll_waits_offset = 0;
             g_scroll_waits_idx++;
        }
        pdata = *(p_List+g_scroll_waits_idx*c_list_waits_size+g_scroll_waits_offset);
        if(pdata == c_null_info)
        {
              g_scroll_waits_idx++;
              g_scroll_waits_offset = 0;
        }               
        }
    while(1)
    {
          if(x_pos >= c_OLED_X_POS_Max)
          {
               break;
          }
          pdata = *(p_List+g_scroll_waits_idx*c_list_waits_size+g_scroll_waits_offset);
          if(pdata == c_null_info)
          {
               g_scroll_waits_idx++;
               g_scroll_waits_offset = 0;
               pdata = *(p_List+g_scroll_waits_idx*c_list_waits_size+g_scroll_waits_offset);
          }
          else
          {
               bmpsize = gui_get_files_x_size(pdata);
               if((c_OLED_X_POS_Max-x_pos)>= bmpsize)
               {
                    load_x_pos_start = 0;
                    load_x_pos_size = bmpsize;
               }
               else
               {
                    load_x_pos_start = 0;
                    load_x_pos_size = c_OLED_X_POS_Max-x_pos;
               }
            }
            x_pos = gui_loadpic_to_ram(x_pos,0,pdata,load_x_pos_start,load_x_pos_size);
            g_scroll_waits_offset++;
            if(g_scroll_waits_offset > (c_list_waits_size-1))
              {
                  g_scroll_waits_offset = 0;
                  g_scroll_waits_idx++;
              }
    }                                
//    if(g_scroll_running_status)
    {
      g_scroll_add_inc+=2;
    }
    gui_updata_to_oled();
   
}
具体思路如下:
第一根据,g_scroll_add_inc算出在屏幕滚动的开始位置算出要显示的第一个图片的ID,并且要算出第一个图片要截取多少去显示
第二,根据要显示的OLED的尺寸,去计算接下来的图片和最后一个图片,至于具体是某个图片则要根据你自己所建立的图片ID所决定,比如这里的图片ID表格T_MuneMainBmpIdxInfo2

要指出的时候,这些图片ID表格和图片长度表格,可以是单数组存放方式,也可以是多维数据的方式,但是在使用的时候,切记要注意越界的问题,所以在建立文件长度表格T_MuneMainBmpIdxInfo2_Size的时候,在最后一个位置我放的数据是c_ListEnd,以防止在访问的时候,越界,至于c_ListEnd 这个标志的值具体是多少,可以根据具体的工程来定,最好不要和图片ID混合,
在此所要说明的是,对于多变和多信息的处理的时候,最好以建立表格的方式去访问,,,,用表格的方式去访问的因素有,工程可维护性强,第二数据结构组织方式易懂,方便,,




路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)