[开源硬件] 【21ic分享赛】 基于51单片机的MP3点播器 续1

[复制链接]
 楼主| jinglixixi 发表于 2016-7-19 16:28 | 显示全部楼层 |阅读模式
三、功能实现
除了硬件方面的设计,要实现相应的功能目标,软件的设计也是不可或缺的。为了更好地进行设计,先来了解一下整体的处理流程。
MP3点播器的处理流程为:
选择歌曲播放的方向(前2项)->选择歌曲->选择播放中的控制功能(后4项)->轮回处理
了解处理后,我们再看一看需要解决的任务,它主要包含3部分:
1)显示功能的设计
2)按键功能的设计
3)通讯功能的设计
在开发过程中,由于所用的单片机只是一个最小系统,使用是借用另一块带有RS232串口通讯功能的单片机来进行开发与测试的,其使用方式如图11所示。
11  外挂RS232串口通讯下载程序

1. 显示功能的设计
受OLED屏显示信息量的限制,在歌曲选择时,是随着选择来更换歌曲名称;而在播放控制时,是通过控制工具栏的符号闪动来提示当前供选择的功能项,其处理效果如图12所示。
图12功能项闪动提示效果

在显示方面,涉及的功能函数有:OLED 初始化函数、清屏函数、字符显示函数、数值显示函数汉字显示函数、及菜单显示函数等。
OLED 初始化函数如下:
  1. void OLED_Init(void)
  2. {        
  3.     OLED_WR_Byte(0xAE,OLED_CMD);
  4.         OLED_WR_Byte(0x00,OLED_CMD);
  5.         OLED_WR_Byte(0x10,OLED_CMD);
  6.         OLED_WR_Byte(0x40,OLED_CMD);  
  7.         OLED_WR_Byte(0xB0,OLED_CMD);
  8.         OLED_WR_Byte(0x81,OLED_CMD);
  9.         OLED_WR_Byte(0xFF,OLED_CMD);  
  10.         OLED_WR_Byte(0xA1,OLED_CMD);
  11.         OLED_WR_Byte(0xA6,OLED_CMD);
  12.         OLED_WR_Byte(0xA8,OLED_CMD);
  13.         OLED_WR_Byte(0x3F,OLED_CMD);
  14.         OLED_WR_Byte(0xC8,OLED_CMD);
  15.         OLED_WR_Byte(0xD3,OLED_CMD);
  16.         OLED_WR_Byte(0x00,OLED_CMD);
  17.         OLED_WR_Byte(0xD5,OLED_CMD);
  18.         OLED_WR_Byte(0x80,OLED_CMD);
  19.         OLED_WR_Byte(0xD8,OLED_CMD);
  20.         OLED_WR_Byte(0x05,OLED_CMD);
  21.         OLED_WR_Byte(0xD9,OLED_CMD);
  22.         OLED_WR_Byte(0xF1,OLED_CMD);
  23.         OLED_WR_Byte(0xDA,OLED_CMD);
  24.         OLED_WR_Byte(0x12,OLED_CMD);
  25.         OLED_WR_Byte(0xDB,OLED_CMD);
  26.         OLED_WR_Byte(0x30,OLED_CMD);
  27.         OLED_WR_Byte(0x8D,OLED_CMD);
  28.         OLED_WR_Byte(0x14,OLED_CMD);
  29.         OLED_WR_Byte(0xAF,OLED_CMD);
  30. }
清屏函数如下:
  1. void OLED_Clear(void)  
  2. {  
  3.         u8 i,n;                    
  4.         for(i=0;i<8;i++)  
  5.         {  
  6.                 OLED_WR_Byte (0xb0+i,OLED_CMD);   
  7.                 OLED_WR_Byte (0x00,OLED_CMD);     
  8.                 OLED_WR_Byte (0x10,OLED_CMD);      
  9.                 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  10.         }
  11. }
在字符显示过程中,要有字符库的支持,以6*8点字模为例其结构如下:
const unsigned char code F6x8[][6] =               
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
。。。
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
。。。
}
字符显示函数如下:
  1. void OLED_Clear(void)  
  2. {  
  3.         u8 i,n;                    
  4.         for(i=0;i<8;i++)  
  5.         {  
  6.                 OLED_WR_Byte (0xb0+i,OLED_CMD);   
  7.                 OLED_WR_Byte (0x00,OLED_CMD);     
  8.                 OLED_WR_Byte (0x10,OLED_CMD);      
  9.                 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  10.         }
  11. }

在字符显示过程中,要有字符库的支持,以6*8点字模为例其结构如下:
const unsigned char code F6x8[][6] =               
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
。。。
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
。。。
}
字符显示函数如下:
  1. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
  2. {             
  3.             unsigned char c=0,i=0;       
  4.                 c=chr-' ';               
  5.                 if(x>Max_Column-1){x=0;y=y+2;}
  6.                 if(Char_Size ==16)
  7.                         {
  8.                         OLED_Set_Pos(x,y);       
  9.                         for(i=0;i<8;i++)
  10.                         OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
  11.                         OLED_Set_Pos(x,y+1);
  12.                         for(i=0;i<8;i++)
  13.                         OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
  14.                         }
  15.                         else
  16.             {       
  17.                                 OLED_Set_Pos(x,y);
  18.                                 for(i=0;i<6;i++)
  19.                                 OLED_WR_Byte(F6x8[c][i],OLED_DATA);
  20.                      }
  21. }
数值显示函数如下:
  1. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
  2. {                
  3.         u8 t,temp;
  4.         u8 enshow=0;                                                  
  5.         for(t=0;t<len;t++)
  6.         {
  7.                 temp=(num/oled_pow(10,len-t-1))%10;
  8.                 if(enshow==0&&t<(len-1))
  9.                 {
  10.                         if(temp==0)
  11.                         {
  12.                                 OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
  13.                                 continue;
  14.                         }else enshow=1;
  15.                 }
  16.                  OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
  17.         }
  18. }
与字符相同,汉字的显示也需要字库的支持,受存储空间的限制这里是自行构建了一个仅供菜单显示用的小字库,其结构如下:
unsigned char code Hzk[][32]={
//点(0) 播(1) 器(2) (3) (4)
{0x00,0x00,0xC0,0x40,0x40,0x40,0x7F,0x48,0x48,0x48,0x48,0xC8,0x08,0x08,0x00,0x00},
{0x80,0x40,0x37,0x04,0x04,0x14,0x64,0x04,0x14,0x64,0x04,0x07,0x10,0xE0,0x00,0x00},/*"",0*/
{0x10,0x10,0xFF,0x10,0x90,0x82,0x56,0x3A,0x12,0x7F,0x11,0x39,0x55,0x90,0x80,0x00},
{0x42,0x82,0x7F,0x01,0x00,0x00,0xFF,0x49,0x49,0x7F,0x49,0x49,0xFF,0x00,0x00,0x00},/*"",1*/
{0x80,0x80,0x9E,0x92,0x92,0x92,0x9E,0xE0,0x80,0x9E,0xB2,0xD2,0x92,0x9E,0x80,0x00},
{0x08,0x08,0xF4,0x94,0x92,0x92,0xF1,0x00,0x01,0xF2,0x92,0x94,0x94,0xF8,0x08,0x00},/*"",2*/
。。。
}
汉字显示函数如下:
  1. void OLED_ShowCHinese(u8 x,u8 y,u8 no)
  2. {                                  
  3.         u8 t,adder=0;
  4.         OLED_Set_Pos(x,y);       
  5.     for(t=0;t<16;t++)
  6.                 {
  7.                                 OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
  8.                                 adder+=1;
  9.        }       
  10.                 OLED_Set_Pos(x,y+1);       
  11.         for(t=0;t<16;t++)
  12.                 {       
  13.                                 OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
  14.                                 adder+=1;
  15.         }                                       
  16. }
受程序存储空间的限制,在设计过程中是采用测试的方法来逐渐添加菜单内容的,在建到十首歌时已达到7K左右(STC89C528K芯片),就没再继续添加,估计还可以添加几首吧。
由于是采用小字库设计菜单,在使用时是按排列顺序来建立映射关系的,设计时出于方便是为每个菜单项设计了一个小函数以供调用,以“放心去飞”为例,其显示函数为:
  1. void cd10()
  2. {   // 放心去飞
  3.         OLED_Clearp();   // 局部清除函数
  4.         OLED_ShowCHinese(18,2,41);  // 放
  5.         OLED_ShowCHinese(36,2,42);  // 心
  6.         OLED_ShowCHinese(54,2,43);  // 去
  7.         OLED_ShowCHinese(72,2,44);  // 飞
  8. }
若想参考更全的OLED资料,可参考“中景园电子0.96OLED显示屏_C51系列_IIC_例程推荐”。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
21ic小喇叭 发表于 2016-7-20 10:41 | 显示全部楼层
分享的都是大牛啊
 楼主| jinglixixi 发表于 2016-7-20 10:46 | 显示全部楼层

过奖了!多谢了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

517

主题

2932

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部