新手村中打满级大BOSS 2025-08-14 15:09 采纳率: 0%
浏览 6
已结题

p10的屏幕,数据重叠显示,如何解决?



/*
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的时序,也都不起作用

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-08-14 15:10
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    在使用 P10 显示屏时,如果出现数据重叠显示的问题,这通常与刷新频率不足、行扫描顺序错误、数据传输逻辑不正确或硬件连接问题有关。以下为详细解决方案和排查步骤:


    一、问题分析

    • 数据重叠显示:意味着屏幕上的图像或文字没有按照预期逐行显示,而是多行同时亮起,导致画面混乱。
    • 可能原因
      • 行地址控制逻辑错误(如 A/B/C/D 引脚未正确设置)。
      • 数据传输顺序错误(如位序不对,导致数据错位)。
      • 刷新率太低,导致画面闪烁或重叠。
      • OE(输出使能)控制不当,导致多个行同时被点亮。

    二、解决方法

    1. 检查并修正行地址控制逻辑

    • 确保行地址选择正确:HUB12 芯片的 A、B、C、D 引脚用于选择当前行号(0~15)。若这些引脚控制错误,会导致行号错乱。
    • 代码示例
    // 行地址控制函数
    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;
            // 其他行号处理...
        }
    }
    

    重点: 确保 AB 引脚的组合能正确表示行号,否则会跳过某些行或重复显示。


    2. 检查数据传输顺序是否正确

    • HUB12 数据传输顺序:通常是高位先传(MSB first),即最高位(bit7)先发送。
    • 代码示例
    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 <<= 1;
        }
    }
    

    重点: 如果数据位顺序颠倒(如 LSB first),会导致数据错位,造成画面混乱。


    3. 确保 OE 控制逻辑正确

    • OE(Output Enable) 是 HUB12 的输出使能信号,低电平有效
    • 必须在每帧数据写入后拉低 OE,以激活当前行
    • 代码示例
    // 写入一行数据
    void writeRowData(uint8_t row, uint8_t *data) {
        hub12SelectRows(row);
        for (int i = 0; i < 8; i++) {
            hub12DataSerialInput(data[i]);
        }
        // 拉低 OE,使能当前行
        LOW_HUB12_OE;
        // 锁存数据
        HIGH_HUB12_LAT;
        LOW_HUB12_LAT;
        // 拉高 OE,关闭当前行
        HIGH_HUB12_OE;
    }
    

    重点: 必须在锁存前拉低 OE,锁存后再拉高,否则会导致多个行同时显示。


    4. 提高刷新率

    • 刷新率不足会导致画面闪烁或重叠,建议将刷新率提高到 60Hz 以上
    • 可通过增加延时或优化数据传输速度实现。
    // 增加延时
    void delay_ms(uint32_t ms) {
        for (uint32_t i = 0; i < ms * 1000; i++);
    }
    
    // 主循环中调用
    for (int i = 0; i < 16; i++) {
        writeRowData(i, Chinese[0]);  // 写入每一行
        delay_ms(1);  // 延时 1ms
    }
    

    重点: 延时不能太短,否则可能导致数据未完全传输就切换行,造成重叠。


    5. 检查硬件连接

    • HC245:确保方向控制(DIR)接 5V,OE 接 GND。
    • HUB12:确认 OE、A、B、C、SCK、LAT、R、G、D 引脚连接正确。
    • 数据线:确保 R、G、D 与 LED 屏的对应引脚匹配。

    三、完整修复后的代码示例

    // 定义控制引脚
    #define HIGH_HUB12_DR     (GPIOB->BSRR = GPIO_Pin_8)
    #define LOW_HUB12_DR      (GPIOB->BRR  = GPIO_Pin_8)
    
    #define HIGH_HUB12_DG     (GPIOC->BSRR = GPIO_Pin_0)
    #define LOW_HUB12_DG      (GPIOC->BRR  = GPIO_Pin_0)
    
    #define HIGH_HUB12_CLK    (GPIOC->BSRR = GPIO_Pin_9)
    #define LOW_HUB12_CLK     (GPIOC->BRR  = GPIO_Pin_9)
    
    #define HIGH_HUB12_LAT    (GPIOC->BSRR = GPIO_Pin_8)
    #define LOW_HUB12_LAT     (GPIOC->BRR  = GPIO_Pin_8)
    
    #define HIGH_HUB12_OE     (GPIOA->BSRR = GPIO_Pin_8)
    #define LOW_HUB12_OE      (GPIOA->BRR  = GPIO_Pin_8)
    
    #define HIGH_HUB12_A      (GPIOA->BSRR = GPIO_Pin_0)
    #define LOW_HUB12_A       (GPIOA->BRR  = GPIO_Pin_0)
    
    #define HIGH_HUB12_B      (GPIOA->BSRR = GPIO_Pin_1)
    #define LOW_HUB12_B       (GPIOA->BRR  = GPIO_Pin_1)
    
    #define HIGH_HUB12_C      (GPIOB->BSRR = GPIO_Pin_5)
    #define LOW_HUB12_C       (GPIOB->BRR  = GPIO_Pin_5)
    
    #define HIGH_HUB12_D      (GPIOB->BSRR = GPIO_Pin_4)
    #define LOW_HUB12_D       (GPIOB->BRR  = GPIO_Pin_4)
    
    // 数据传输函数
    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 <<= 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;
            // 其他行号可继续添加
        }
    }
    
    // 写入一行数据
    void writeRowData(uint8_t row, uint8_t *data) {
        hub12SelectRows(row);
        for (int i = 0; i < 8; i++) {
            hub12DataSerialInput(data[i]);
        }
        // 拉低 OE,使能当前行
        LOW_HUB12_OE;
        // 锁存数据
        HIGH_HUB12_LAT;
        LOW_HUB12_LAT;
        // 拉高 OE,关闭当前行
        HIGH_HUB12_OE;
    }
    
    // 延时函数
    void delay_ms(uint32_t ms) {
        for (uint32_t i = 0; i < ms * 1000; i++);
    }
    
    // 主循环
    void displayLoop() {
        while (1) {
            for (int i = 0; i < 16; i++) {
                writeRowData(i, Chinese[0]);
                delay_ms(1);
            }
        }
    }
    

    四、总结

    1. 检查行地址控制逻辑,确保 A/B 引脚组合正确。
    2. 验证数据传输顺序,确保是 MSB first。
    3. 控制 OE 信号,确保只有一行被点亮。
    4. 适当提高刷新率,避免画面重叠。
    5. 检查硬件连接,确保 HC245 和 HUB12 正确配置。

    如果仍然存在问题,请提供完整的电路图或更多代码片段,以便进一步定位问题。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月25日
  • 创建了问题 8月14日