本帖最后由 额企鹅企鹅 于 2025-11-17 12:57 编辑
/**************************************************************************************************** * 文件名: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段数码管 如何单独控制亮灭 和组合控制呀 我的驱动初始化有问题吗
|
|