[技术问答] HC32F176KATA+LCD驱动问题

[复制链接]
897|1
额企鹅企鹅 发表于 2025-11-11 15:29 | 显示全部楼层 |阅读模式
, , , ,
本帖最后由 额企鹅企鹅 于 2025-11-17 12:57 编辑

368066912e51a2da00.png /****************************************************************************************************                                *  文件名:ocp_lcd.c
                                *
                                *  文件描述:LCD的驱动程序
                                *
                                *  创建人:
                                *
                                *  创建时间:
                                *
                                *  版本号:
                                *
                                *  修改记录:


****************************************************************************************************/

#include "include.h"


// #################### 关键配置:极性适配(根据暗**况切换)####################
// 1=正向极性(RAM位=1点亮,0熄灭);0=反向极性(RAM位=0点亮,1熄灭)
#define LCD_POLARITY_POSITIVE  1  // 先试0(解决暗色常用),不行再改1

// 2. 显示单元与SEG映射(需根据你的屏调试修正!参考之前的调试方法)

typedef struct {
    uint8_t seg_cnt;          // 该单元包含的SEG数量(7段数码管填7)
    uint8_t seg_list[8];      // 对应的SEG编号(a-g段的SEG序号)
} Lcd_UnitSegMap_t;

#define LCD_UNIT_TOTAL 4  // 假设有4个独立数码管(如6、7、8、P)
const Lcd_UnitSegMap_t g_astLcdUnitMap[LCD_UNIT_TOTAL] = {
    // 数码管6(对应COM1):包含6F、6G、6E、6A、6B、6C、6D
    {7, {6, 7, 8, 9, 10, 11, 12}},  // 假设这些SEG仅属于数码管6
    // 数码管7(对应COM2):包含7F、7A、7G、7B、7E、7C、7D
    {7, {13, 14, 15, 16, 17, 18, 19}}, // 专属SEG,不与其他共享
    // 数码管8(对应COM3):包含8F、8A、8G、8B、8E、8C、8D
    {7, {20, 21, 22, 23, 24, 25, 26}},
    // 数码管P(对应COM4):包含P4、P5、P6、P3、P2、P1、S1
    {7, {27, 28, 29, 30, 31, 0, 1}},
};
// 每个数码管对应的COM编号(0=COM0,1=COM1,2=COM2,3=COM3)
const uint8_t g_u8LcdUnitCom[LCD_UNIT_TOTAL] = {1, 2, 3, 4}; // 示例:数码管6对应COM1(索引1)

// #################### 增强型清屏函数(二次清屏+延时,彻底清RAM)####################
void Lcd_EnhancedClear(void) {
    Lcd_ClearDisp();       // 第一次清屏(清RAM0~15为0)
    delay_us(200);         // 延时200us(等待LCD偏压稳定,避免残留)
    Lcd_ClearDisp();       // 第二次清屏(确保所有RAM位清0)
}

// #################### LCD RAM读取函数(DDL库未提供,必须实现)####################
void Lcd_ReadRam(uint8_t u8RamIdx, uint32_t *pu32RamVal) {
    if (u8RamIdx > 15 || pu32RamVal == NULL) {
        *pu32RamVal = 0;
        return;
    }
    // RAM0~RAM15地址连续,直接偏移访问
    volatile uint32_t *pRam = &(M0P_LCD->RAM0) + u8RamIdx;
    *pu32RamVal = *pRam;
}

void Lcd_ControlUnit(uint8_t u8UnitIdx, uint8_t u8OnOff) {
    if (u8UnitIdx >= LCD_UNIT_TOTAL) return;

    uint8_t i;
    uint32_t u32RamVal;
    const Lcd_UnitSegMap_t *pstUnit = &g_astLcdUnitMap[u8UnitIdx];
    uint8_t u8ComIdx = g_u8LcdUnitCom[u8UnitIdx]; // 获取该数码管对应的COM

    // 只操作该COM对应的RAM(不再遍历所有4个COM)
    Lcd_ReadRam(u8ComIdx, &u32RamVal);

    for (i = 0; i < pstUnit->seg_cnt; i++) {
        uint8_t u8SegIdx = pstUnit->seg_list;
        if (u8SegIdx > 31) continue;

        // 根据极性控制SEG
        if (LCD_POLARITY_POSITIVE == 1) {
            u32RamVal = (u8OnOff == 1) ? (u32RamVal | (1UL << u8SegIdx)) : (u32RamVal & ~(1UL << u8SegIdx));
        } else {
            u32RamVal = (u8OnOff == 1) ? (u32RamVal & ~(1UL << u8SegIdx)) : (u32RamVal | (1UL << u8SegIdx));
        }
    }

    Lcd_WriteRam(u8ComIdx, u32RamVal); // 仅写回对应COM的RAM
}

// 测试函数:仅向指定COM(RAM行)写入SEG数据
void Lcd_TestSegWithCom(uint8_t u8SegIdx, uint8_t u8ComIdx)
{
    if (u8SegIdx > 31 || u8ComIdx > 3)
                        return; // 仅COM0~COM3有效
    Lcd_EnhancedClear();
    uint32_t u32RamVal = 0;
               
    // 只操作目标COM对应的RAM行
    if (LCD_POLARITY_POSITIVE == 1)
                {
        u32RamVal = 1UL << u8SegIdx; // 正向极性:置位SEG
    }
          else
                {
        u32RamVal = ~(1UL << u8SegIdx); // 反向极性:清零SEG
    }
    Lcd_WriteRam(u8ComIdx, u32RamVal); // 仅写入目标COM的RAM
}

/*******************************************************************************  
            *函数名称:void void App_PortCfg(void)

            *函数功能:LCD的GPIO配置函数

            *入口参数:无

            *出口参数:无

            *备注:无

*******************************************************************************/
void App_PortCfg(void)
{
        Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟
        
        Gpio_SetAnalogMode(GpioPortA, GpioPin9);  //COM0
        Gpio_SetAnalogMode(GpioPortA, GpioPin10); //COM1
        Gpio_SetAnalogMode(GpioPortA, GpioPin11); //COM2
        Gpio_SetAnalogMode(GpioPortA, GpioPin12); //COM3   

        Gpio_SetAnalogMode(GpioPortA, GpioPin8);  //SEG0
        Gpio_SetAnalogMode(GpioPortC, GpioPin9);  //SEG1
        Gpio_SetAnalogMode(GpioPortC, GpioPin8);  //SEG2
        Gpio_SetAnalogMode(GpioPortC, GpioPin7);  //SEG3
        Gpio_SetAnalogMode(GpioPortC, GpioPin6);  //SEG4
        Gpio_SetAnalogMode(GpioPortB, GpioPin15); //SEG5
        Gpio_SetAnalogMode(GpioPortB, GpioPin14); //SEG6
        Gpio_SetAnalogMode(GpioPortB, GpioPin13); //SEG7
        Gpio_SetAnalogMode(GpioPortB, GpioPin12); //SEG8
        Gpio_SetAnalogMode(GpioPortB, GpioPin1);  //SEG12
        Gpio_SetAnalogMode(GpioPortB, GpioPin0);  //SEG13
        Gpio_SetAnalogMode(GpioPortC, GpioPin5);         //SEG14
        Gpio_SetAnalogMode(GpioPortC, GpioPin4);         //SEG15
        Gpio_SetAnalogMode(GpioPortA, GpioPin7);         //SEG16
        Gpio_SetAnalogMode(GpioPortA, GpioPin6);         //SEG17
               
        stc_gpio_cfg_t stcGpioCfg;        

        DDL_ZERO_STRUCT(stcGpioCfg);
        
        stcGpioCfg.enDir = GpioDirOut;    // 输出方向
        stcGpioCfg.enDrv = GpioDrvH;      // 高驱动能力
        stcGpioCfg.enPu = GpioPuDisable;  // 禁用上拉
        stcGpioCfg.enPd = GpioPdDisable;  // 禁用下拉

        //        LCD led配置
  Gpio_ClrIO( GpioPortB, GpioPin2 );
        Gpio_Init( GpioPortB, GpioPin2, &stcGpioCfg );      
        Gpio_SetIO( GpioPortB,GpioPin2 );
}


/*******************************************************************************  
            *函数名称:void App_LcdCfg(void)

            *函数功能:LCD配置函数

            *入口参数:无

            *出口参数:无

            *备注:无

*******************************************************************************/
void App_LcdCfg(void)
{
          stc_lcd_cfg_t LcdInitStruct;
    stc_lcd_segcom_t LcdSegCom;

    LcdSegCom.u32Seg0_31 = 0xFFFC0E00;                              ///< 配置LCD_POEN0寄存器 开启SEG0~SEG8,SEG12~SEG17
    LcdSegCom.stc_seg32_51_com0_8_t.seg32_51_com0_8 = 0xffffffff;   ///< 初始化LCD_POEN1寄存器 全部关闭输出端口
    LcdSegCom.stc_seg32_51_com0_8_t.segcom_bit.Com0_3 = 0x0F;       ///< 使能COM0~COM3
    LcdSegCom.stc_seg32_51_com0_8_t.segcom_bit.Mux = 0;             ///< 内部电阻模式
    LcdSegCom.stc_seg32_51_com0_8_t.segcom_bit.Seg32_35 = 0;                        
    Lcd_SetSegCom(&LcdSegCom);                                      ///< LCD COMSEG端口配置

    LcdInitStruct.LcdBiasSrc = LcdInResMidPower;                   ///< 偏置源选择: 内部电阻分压,中功耗模式
    LcdInitStruct.LcdDuty = LcdDuty4;                              ///< 1/4duty
    LcdInitStruct.LcdBias = LcdBias3;                              ///< 1/3 BIAS
    LcdInitStruct.LcdCpClk = LcdClk2k;                             ///< 电压泵时钟频率选择2kHz
    LcdInitStruct.LcdScanClk = LcdClk256hz;                        ///< LCD扫描频率选择256Hz
                LcdInitStruct.LcdMode = LcdMode1;                              ///< 选择模式1:同一个COM的不同SEG在同一个字节中
    LcdInitStruct.LcdClkSrc = LcdRCL;                              ///< LCD时钟选择RCL
    LcdInitStruct.LcdEn   = LcdEnable;                             ///< 使能LCD模块
    Lcd_Init(&LcdInitStruct);
}


/*******************************************************************************  
            *函数名称:void Ocp_Lcd_Init( void )

            *函数功能:LCD初始化函数

            *入口参数:无

            *出口参数:无

            *备注:无

*******************************************************************************/
void Ocp_Lcd_Init( void )
{
    Sysctrl_ClkSourceEnable(SysctrlClkRCL,TRUE);            ///< 使能RCL时钟
    Sysctrl_SetRCLTrim(SysctrlRclFreq32768);                ///< 配置内部低速时钟频率为32.768kHz

    Sysctrl_SetPeripheralGate(SysctrlPeripheralLcd,TRUE);   ///< 开启LCD时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);  ///< 开启GPIO时钟

    App_PortCfg();               ///< LCD端口配置
    App_LcdCfg();                ///< LCD模块配置

    Lcd_EnhancedClear();             ///< 清屏

}

int main(void)
{     
        System_Init();

        
        Lcd_TestSegWithCom(0, 0); // 测试SEG2在COM1(RAM1)上的段
        
        while( 1 )
        {

        }
}

我使用上述点亮函数 点亮的是1B 1G 1C S6这4段数码管 如何单独控制亮灭 和组合控制呀 我的驱动初始化有问题吗

 楼主| 额企鹅企鹅 发表于 2025-11-11 16:12 | 显示全部楼层
有没有好心人 第一次调LCD+小华
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

29

帖子

0

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