在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混合,
在此所要说明的是,对于多变和多信息的处理的时候,最好以建立表格的方式去访问,,,,用表格的方式去访问的因素有,工程可维护性强,第二数据结构组织方式易懂,方便,,