本帖最后由 jinglixixi_457498010 于 2023-7-13 09:21 编辑

在通常的情况下,我们所所用的显示器件多是数码管、液晶屏、OLED屏及TFT屏。但在公共场合要显示信息,就要有较大尺寸以便观察。
通常多使用半板来拼接成较大的广告牌,这里使用的是一款P4.75的红色点阵板,其显示分辨率为16*64像素点。

image.png
图1 点阵屏外观

该点阵屏采用的接口方式为HUB08,各引脚的名称如图2所示。
image.png
图2  HUB08接口

该点阵屏与开发板的连接关系为:
A---PB4
B---PB5
C---PA6
D---PB7
R1 ---PC2
OE ---PC3
LAT ---PC1
CLK---PC0

所用引脚输出高低电平的语句定义为:
#define LA_high   gpio_set_level(GPIO_PB4, 1) // A
#define LA_low    gpio_set_level(GPIO_PB4, 0)
#define LB_high   gpio_set_level(GPIO_PB5, 1) // B
#define LB_low    gpio_set_level(GPIO_PB5, 0)
#define LC_high   gpio_set_level(GPIO_PB6, 1) // C
#define LC_low    gpio_set_level(GPIO_PB6, 0)
#define LD_high   gpio_set_level(GPIO_PB7, 1) // D
#define LD_low    gpio_set_level(GPIO_PB7, 0)
#define LR1_high  gpio_set_level(GPIO_PC2, 1) // R1
#define LR1_low   gpio_set_level(GPIO_PC2, 0)
#define CLK_high  gpio_set_level(GPIO_PC0, 1) // CLK
#define CLK_low   gpio_set_level(GPIO_PC0, 0)
#define LEN_high  gpio_set_level(GPIO_PC3, 1) // CS
#define LEN_low   gpio_set_level(GPIO_PC3, 0)
#define LSTB_high  gpio_set_level(GPIO_PC1, 1) // STB
#define LSTB_low   gpio_set_level(GPIO_PC1, 0)

所用引脚的初始化函数为:
  1. void gpio_init (void)
  2. {
  3.         gpio_function_en(GPIO_PB4);
  4.         gpio_output_en(GPIO_PB4);
  5.         gpio_function_en(GPIO_PB5);
  6.         gpio_output_en(GPIO_PB5);
  7.         gpio_function_en(GPIO_PB6);
  8.         gpio_output_en(GPIO_PB6);
  9.         gpio_function_en(GPIO_PB7);
  10.         gpio_output_en(GPIO_PB7);
  11.         gpio_function_en(GPIO_PC0);
  12.         gpio_output_en(GPIO_PC0);
  13.         gpio_function_en(GPIO_PC1);
  14.         gpio_output_en(GPIO_PC1);
  15.         gpio_function_en(GPIO_PC2);
  16.         gpio_output_en(GPIO_PC2);
  17.         gpio_function_en(GPIO_PC3);
  18.         gpio_output_en(GPIO_PC3);
  19. }
1. 电子时钟为实现数字符号的显示,以字模提取软件所构建的字库存储结构为:
  1. uint8_t S[]={
  2. 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,/*"0",0*/
  3. 0x00,0x00,0x00,0x08,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00,/*"1",1*/
  4. 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x20,0x20,0x10,0x08,0x04,0x42,0x7E,0x00,0x00,/*"2",2*/
  5. ...
  6. 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,/*":",10*/
  7. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"-",11*/
  8. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  9. };
点阵板发送数据的函数为:
  1. voidOutByte (u16 dat)
  2. {
  3.     u8 i=0 ;
  4.     for(i=0;i<16;i++)
  5.     {
  6.         CLK_low;
  7.         if(dat&0x0001)
  8.         {
  9.             LR1_high;
  10.         }
  11.         else
  12.         {
  13.             LR1_low;
  14.         }
  15.         dat=dat>>1;
  16.         delay_us(10);
  17.         CLK_high;
  18.         delay_us(10);
  19.     }
  20. }
输出行地址的函数为:
  1. voidSeleRow(uint8_t Nd)
  2. {
  3.     uint8_t N;
  4.     N=Nd;
  5.     N=N%16;
  6.     if(N&0x01)   LA_high;
  7.     else  LA_low;
  8.     if (N&0x02)  LB_high;
  9.     else  LB_low;
  10.     if (N&0x04)  LC_high;
  11.     else  LC_low;
  12.     if (N&0x08)  LD_high;
  13.     else  LD_low;
  14. }
发送多列数据的函数为:
  1. voidDisCol (u16 lenght)
  2. {
  3.     u16 dat;
  4.     uint8_t ml=0;
  5.     while(lenght--)
  6.     {
  7.           dat=(S[sj[ml+1]*16+ScanRow]<<8)+S[sj[ml]*16+ScanRow];
  8.           OutByte (dat);
  9.           ml=ml+2;
  10.     }
  11. }
实现显示输出的函数为:
  1. voidDisplay_B(void)
  2. {
  3.     DisCol_B(4);
  4.     LEN_high;
  5.     LSTB_high;
  6.     LSTB_low;
  7.     SeleRow(ScanRow);
  8.     LEN_low;
  9.     ScanRow++;
  10.     if(ScanRow>15)  ScanRow=0;
  11. }
由于Telink B91没有专用的RTC计时器,故要在显示刷新中实现计时处理,只能通过计算显示的耗时来推算出一个秒计时器来替代RTC的作用。实现图2所示的计时效果,其主程序为:
  1. int main (void)
  2. {
  3.         unsignedint i=0,h=8,m=30,s=0;
  4.         sys_init(LDO_1P4_LDO_1P8, VBAT_MAX_VALUE_GREATER_THAN_3V6);
  5.         user_read_flash_value_calib();
  6.         CCLK_24M_HCLK_24M_PCLK_24M;
  7.         user_init();
  8.         delay_ms(1000);
  9.         ScanRow=0;
  10.         gpio_init (void)
  11.         delay_ms(100);
  12.         while (1) {
  13.         for(i=0;i<500;i++)
  14.         {
  15.                     Display ();
  16.         }
  17.         s=s+1;
  18.         if(s==60)
  19.         {
  20.                  s=0;
  21.                  m=m+1;
  22.         }
  23.         sj[6]=s/10;
  24.         sj[7]=s%10;
  25.         if(m==60)
  26.         {
  27.                  m=0;
  28.                  h=h+1;
  29.         }
  30.         sj[3]=m/10;
  31.         sj[4]=m%10;
  32.         if(h==60)
  33.         {
  34.                  h=0;
  35.         }
  36.         sj[0]=h/10;
  37.         sj[1]=h%10;
  38.         }
  39.         return 0;
  40. }
image.png
图2 电子时钟


2. 汉字显示为实现汉字的显示,以字模提取软件所构建的字库存储结构为:
  1. uint8_t V[]={
  2. //远上寒山石径斜白云生处有人家...
  3. 0x00,0x00,0xF8,0x23,0x00,0x10,0x00,0x10,0x00,0x00,0xFC,0x07,0x20,0xF1,0x20,0x11,
  4. 0x20,0x11,0x20,0x11,0x24,0x11,0x24,0x12,0x24,0x12,0x1C,0x14,0x00,0x28,0xFE,0x47,// 0
  5. 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0xF8,0x03,0x00,0x02,
  6. 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0xFE,0xFF,0x00,0x00,
  7. ...  
  8. };
点阵板发送数据的函数为:
  1. voidOutByte(uint16_t dat)
  2. {
  3.     uint8_t i=0 ;
  4.     for(i=0;i<16;i++)
  5.     {
  6.         CLK_low;
  7.         delay_us(10);
  8.         if(dat&0x8000)
  9.         {
  10.             LR1_high;
  11.         }
  12.         else
  13.         {
  14.             LR1_low;
  15.         }
  16.         dat=dat<<1;
  17.         delay_us(10);
  18.         CLK_high;
  19.     }
  20. }
发送多列数据的函数为:
  1. voidDisCol (uint16_t lenght)
  2. {
  3.     uint16_t dat;
  4.     uint8_t m=8;
  5.     m=mm;
  6.     while(lenght--)
  7.     {
  8.           dat=(V[m*32+ScanRow*2+1]<<8)+V[m*32+ScanRow*2];
  9.           OutByte(dat);
  10.           m=m+1;
  11.     }
  12. }
实现显示输出的函数为:
  1. voidDisplay (void)
  2. {
  3.     DisCol (4);
  4.     LEN_high;
  5.     LSTB_high;
  6.     LSTB_low;
  7.     SeleRow(ScanRow);
  8.     LEN_low;
  9.     ScanRow++;
  10.     if(ScanRow>15)  ScanRow=0;
  11. }
受显示板显示规格的限制,要显示一首唐诗,必须通过分屏显示来完成,或通过屏幕滚动的方式来实现。这里采用的是多屏显示的方式,其实现图3所示效果的主程序为:
  1. int main (void)
  2. {
  3.         unsignedint i=0;
  4.         sys_init(LDO_1P4_LDO_1P8, VBAT_MAX_VALUE_GREATER_THAN_3V6);
  5.         user_read_flash_value_calib();
  6.         CCLK_24M_HCLK_24M_PCLK_24M;
  7.         user_init();
  8.         delay_ms(100);
  9.         ScanRow=0;
  10.         delay_ms(100);
  11.         while (1) {
  12.         for(i=0;i<1500;i++)
  13.         {
  14.                     Display ();
  15.         }
  16.         mm=(mm+4)%32;
  17.         }
  18.         return 0;
  19. }

image.png
图3 汉字显示效果