/*
HC245
DIR接5V OE接GND A->B
HUB12
第一列引脚,从上到下为OE,N,N,N,N,N,N,N
第二列引脚,从上到下为A,B,C,SCK,LAT,R,G,D
*/
// 数据线 - 红色 (R -> PB8)
#define HIGH_HUB12_DR (GPIOB->BSRR = GPIO_Pin_8)
#define LOW_HUB12_DR (GPIOB->BRR = GPIO_Pin_8)
// 数据线 - 绿色 (G -> PC0)
#define HIGH_HUB12_DG (GPIOC->BSRR = GPIO_Pin_0)
#define LOW_HUB12_DG (GPIOC->BRR = GPIO_Pin_0)
// 时钟线 (SCK / SH_CP -> PC9)
#define HIGH_HUB12_CLK (GPIOC->BSRR = GPIO_Pin_9)
#define LOW_HUB12_CLK (GPIOC->BRR = GPIO_Pin_9)
// 锁存线 (LAT / ST_CP -> PC8)
#define HIGH_HUB12_LAT (GPIOC->BSRR = GPIO_Pin_8)
#define LOW_HUB12_LAT (GPIOC->BRR = GPIO_Pin_8)
// 输出使能 (OE -> PA8, 低电平有效)
#define HIGH_HUB12_OE (GPIOA->BSRR = GPIO_Pin_8)
#define LOW_HUB12_OE (GPIOA->BRR = GPIO_Pin_8)
// 行地址线 A (A -> PA0)
#define HIGH_HUB12_A (GPIOA->BSRR = GPIO_Pin_0)
#define LOW_HUB12_A (GPIOA->BRR = GPIO_Pin_0)
// 行地址线 B (B -> PA1)
#define HIGH_HUB12_B (GPIOA->BSRR = GPIO_Pin_1)
#define LOW_HUB12_B (GPIOA->BRR = GPIO_Pin_1)
// 行地址线 C (C -> PB5)
#define HIGH_HUB12_C (GPIOB->BSRR = GPIO_Pin_5)
#define LOW_HUB12_C (GPIOB->BRR = GPIO_Pin_5)
// 行地址线 D (D -> PB4)
#define HIGH_HUB12_D (GPIOB->BSRR = GPIO_Pin_4)
#define LOW_HUB12_D (GPIOB->BRR = GPIO_Pin_4)
/* 显示汉字总数 */
#define WORD_NUM 4
/* 每行显示的字节数 */
#define SCAN_NUM (8 * WORD_NUM)
u8 Chinese[4][32] =
{
{
0x01, 0x02, //第1行
0x03, 0x04, //第2行
0x05, 0x06, //第3行
0x07, 0x08,//第0行
0x21, 0x22, //第5行
0x23, 0x24, //第6行
0x25, 0x26, //第7行
0x27, 0x28,//第4行
0x31, 0x32, //第9行
0x33, 0x34, //第10行
0x35, 0x36, //第11行
0x37, 0x38,//第8行
0x41, 0x42, //第13行
0x43, 0x44, //第14行
0x45, 0x46, //第15行
0x47, 0x48,//第12行
},
{
0x08,0x08,0x08,0x08,0x3F,0x24,0x24,0xA4,0x24,0x12,0x14,0x08,0x14,0x22,0x21,0x00,
0x00,0x3F,0x20,0x10,0x08,0x04,0x04,0x7F,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x02,
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{
0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
};
uint8_t dispram[128] = {0};
void hub12DataSerialInput(uint8_t data){
uint8_t i;
for( i = 0; i < 8; i++){
if(data & 0x80){
LOW_HUB12_DR;
}else{
HIGH_HUB12_DR;
}
LOW_HUB12_CLK;
HIGH_HUB12_CLK;
data = data << 1;
}
}
void hub12SelectRows(uint8_t rows){
switch(rows){
case 0:
LOW_HUB12_A;
LOW_HUB12_B;
break;
case 1:
HIGH_HUB12_A;
LOW_HUB12_B;
break;
case 2:
LOW_HUB12_A;
HIGH_HUB12_B;
break;
case 3:
HIGH_HUB12_A;
HIGH_HUB12_B;
break;
default:
break;
}
}
//高低字节交换,0b10110000 → 0b00001101
u8 SwapByte(u8 data)
{
data=(data<<4)|(data>>4);
data=((data<<2)&0xcc)|((data>>2)&0x33);
data=((data<<1)&0xaa)|((data>>1)&0x55);
return data;
}
//led屏驱动显示模块,HUB12 是 从右到左 移位的
void hub12Display(uint16_t bright,uint8_t *buffer)
{
for(u8 s=0; s<4; s++){ // 4个行组(1/4扫描)
hub12SelectRows(s);
LOW_HUB12_LAT;
for(int i=0; i<SCAN_NUM; i++) {
hub12DataSerialInput(buffer[s*SCAN_NUM + i]);
}
HIGH_HUB12_LAT;
LOW_HUB12_OE;
Delay_us(bright);
HIGH_HUB12_OE;
}
}
void WriteScreen(u8 locatin, u8 *text)
{
u8 i;//行号
u8 j;//显示缓冲区的标号
u8 k;
u8 buffer[32];
/* 字模处理 */
for(k = 0; k < 32; k++)buffer[k] = text[31 - k]; //从左到右,从上到下依次显示
printf("\r从左到右(交换后): ");
for(int k = 0; k < 32; k++) printf("%02X ", buffer[k]);
printf("\n");
for(k = 0; k < 32; k++)buffer[k] = SwapByte(buffer[k]); //高低字节交换
printf("\r高低位(交换后): ");
for(int k = 0; k < 32; k++) printf("%02X ", buffer[k]);
printf("\n");
/* 写缓冲区 */
for(i = 0; i < 4; i++)// 4组扫描行
{
// 当 i=0:j从 0-31 (第0行组)
// 当 i=1:j从 32-63 (第1行组)
// 当 i=2:j从 64-95 (第2行组)
// 当 i=3:j从 96-127(第3行组)
for(j = (SCAN_NUM * i); j < SCAN_NUM * (i + 1); j++)
{
if((j >= ((SCAN_NUM * i) + 8 * locatin)) && (j <= ((SCAN_NUM * i + 3) + 8 * locatin)))
{
dispram[j] = buffer[(7 - 2 * i) + 8 * (j - 8 * locatin - SCAN_NUM * i)]; //一个汉字的右边字节
printf("右边:0x%02X ",dispram[j]);
}
if((j >= ((SCAN_NUM * i + 4) + 8 * locatin)) && (j <= ((SCAN_NUM * i + 7) + 8 * locatin)))
{
dispram[j] = buffer[(6 - 2 * i) + 8 * (j - 8 * locatin - SCAN_NUM * i - 4)]; //一个汉字的左边字节
printf(" 左边:0x%02X",dispram[j]);
}
}
}
printf("显示缓存内容:\n");
for(int i = 0; i < 128; i++)
{
if(i%8==0)
{
printf("\n");
}
printf("0x%02X ",dispram[i]);
}
}
//静态显示汉字
void StaticDisplay(uint8_t font[4][32])
{
memset(dispram, 0, sizeof(dispram)); // 清空显存
for(u8 locatin=0;locatin<4;locatin++)
{
WriteScreen(locatin, font[locatin]);
}
}
在16*64的LED屏幕上,使用4/1扫和HUB12的接口驱动方式
4/1扫是0,4,8,12行
4/2扫是1,5,9,13行
4/3扫是2,6,10,14行
4/4扫是3,7,11,15行
上述程序,在执行的时候,总会把4/1扫是0,4,8,12行的数据,和4/4扫是3,7,11,15行的数据,全部叠加在3,7,11,15行
比如,第0行的数据为,0001 0001
第3行的数据为0100 0100
然后实际在第三行显示的是0101 0101.也就是0001 0001和0100 0100融合在一起了
这是什么原因?如何从软件方面解决?
使用16/1扫和调整LAT,CLK的时序,也都不起作用