1731|0

206

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【上海航芯 ACM32F070开发板+触控功能评估板】03.不一样的LCD显示实现方式 [复制链接]

 

ACM32F070系列MCU带有一个段式LCD液晶显示控制器,最多支持8个公用端子(COM)和40个区段端子(SEG),可以驱动160(4*40)或者288(8*36)个LCD段位显示。主要特性如下:

 高度灵活的帧速率控制
 支持静态、 1/2、 1/3、 1/4、 1/6 和 1/8 占空比
 支持 1/2、 1/3、 1/4 偏置
 多达 16 个寄存器的 LCD 数据 RAM
 可通过软件配置 LCD 的对比度
 支持 A 类、 B 类波形
 2 种驱动波形生成方式
- 内部电阻分压、外部电阻分压
- 可选的滤波电容
- 可通过软件配置内部电阻分压方式的功耗,从而匹配 LCD 面板所需的电容电荷
 支持低功耗模式: LCD 控制器可在 Active、 Sleep、 Stop 模式下进行显示
 可配置帧中断
 支持 LCD 闪烁功能且可配置多种闪烁频率
 未使用的 LCD 区段和公共引脚可配置为数字或模拟功能
 

官方程序中提供了LCD_TK的示例程序,对于LCD的实现部分支持了3款液晶显示屏,我们拿到手的开发上自带液晶屏型号为:YR1618A,对于液晶屏底层显示驱动,官方的示例程序定义很多的宏,然后通过对这些宏定义来封装函数实现功能,看了半天的官方示例程序,也就看懂他的编程想法,具体的宏定义需要一个一个对照LCD的真值表与MCU的连接方式去修改,如果再切换一个屏的时候,修改的内容和工作量想想就有点退缩了,所以在这边介绍和推荐我常用的一套LCD实现方式:通过查表、映射的方式来实现LCD的显示功能。

 

此方法程序更具有可读性、移植方便、兼容性强、实现的功能根据显示需要可作灵活调整……具体的我们需要准备如下几部分:

1、对于8段组合显示的内容,我们穷举了可以显示的所有字符,我们可以通过查表的方式,获取到这些显示字符对应的A~G段的显示状态;

2、对照LCD真值表,将LCD引脚与MCU引脚的硬件连接关系映射成一个表格,通过这个表格我们可以方便的查找到需要显示的段位所对应的COM和SEG下标

3、通过COM和SEG下标去操作MCU内LCD的显示缓存寄存器,将显示内容体现的屏幕上

 

具体的代码实现如下所示:

const LCD_CODING_TypeDef LCD_CODE_Table[38] = 
{
    {' ', 0x00},
    {'0', 0x3F},
    {'1', 0x06},
    {'2', 0x5B},
    {'3', 0x4F},
    {'4', 0x66},
    {'5', 0x6D},
    {'6', 0x7D},
    {'7', 0x07},
    {'8', 0x7F},
    {'9', 0x6F},
    {'A', 0x77},
    {'b', 0x7C},
    {'c', 0x58},
    {'C', 0x39},
    {'d', 0x5E},
    {'E', 0x79},
    {'F', 0x71},
    {'g', 0x6F},
    {'H', 0x76},
    {'h', 0x74},
    {'i', 0x04},
    {'I', 0x30},
    {'J', 0x1E},
    {'l', 0x30},
    {'L', 0x38},
    {'n', 0x54},
    {'o', 0x5C},
    {'O', 0x3F},
    {'P', 0x73},
    {'q', 0x67},
    {'r', 0x50},
    {'S', 0x6D},
    {'t', 0x78},
    {'u', 0x1C},
    {'U', 0x3E},
    {'y', 0x6E},
    {'-', 0x40},
};

 

const char LCD_NAME_Table[LCD_COM_NUMBER][LCD_SEG_NUMBER][4] =
{
    {"1A ", "1B ", "2A ", "2B ", "3A ", "3B ", "4A ", "4B ", "S9 ", "S10", "---", "---", "---", "7B ", "5B ", "5A ", "---", "---", "---", "7A ", "---", "---", "6A ", "6B ", "S1 ", "8A ", "8B ", "S14", "---", "---", "---", "---"},
    {"1F ", "1G ", "2F ", "2G ", "3F ", "3G ", "4F ", "4G ", "S8 ", "S11", "---", "---", "---", "7G ", "5G ", "5F ", "---", "---", "---", "7F ", "---", "---", "6F ", "6G ", "S2 ", "8F ", "8G ", "S16", "---", "---", "---", "---"},
    {"1E ", "1C ", "2E ", "2C ", "3E ", "3C ", "4E ", "4C ", "S7 ", "S12", "---", "---", "---", "7C ", "5C ", "5E ", "---", "---", "---", "7E ", "---", "---", "6E ", "6C ", "S3 ", "8E ", "8C ", "S15", "---", "---", "---", "---"},
    {"1D ", "1P ", "2D ", "2P ", "3D ", "3P ", "4D ", "L1 ", "S6 ", "S5 ", "---", "---", "---", "7P ", "5P ", "5D ", "---", "---", "---", "7D ", "---", "---", "6D ", "6P ", "S4 ", "8D ", "L2 ", "S13", "---", "---", "---", "---"},
};

 

/*******************************************************************************
 * [url=home.php?mod=space&uid=159083]@brief[/url] * @param       
 * @retval      
 * [url=home.php?mod=space&uid=1020061]@attention[/url] *******************************************************************************/
void LCD_WriteBit(uint8_t COMn, uint8_t SEGn, uint8_t State)
{
    if(State) LCD_Buffer[COMn] |=  (0x00000001 << SEGn);
    else      LCD_Buffer[COMn] &= ~(0x00000001 << SEGn);

    HAL_LCD_Write(&LCD_Handle, COMn, LCD_Buffer[COMn]);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
uint8_t LCD_SearchCode(char ch)
{
    for(uint8_t i = 0; i < 38; i++)
    {
        if(ch == LCD_CODE_Table[i].ch)
        {
            return LCD_CODE_Table[i].Data;
        }
    }

    return 0xFF;
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_SearchName(char *str, uint8_t *COMn, uint8_t *SEGn)
{
    for(uint8_t i = 0; i < LCD_COM_NUMBER; i++)
    {
        for(uint8_t j = 0; j < LCD_SEG_NUMBER; j++)
        {
            if(strcmp(str, LCD_NAME_Table[i][j]) == 0)
            {
                *COMn = i; *SEGn = j; return;
            }
        }
    }

    *COMn = 0xFF;
    *SEGn = 0xFF;
}

 

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_Init(void)
{
    GPIO_InitTypeDef        GPIOx_Handle;
    LCD_InResInitTypeDef    LCD_InRes;
    LCD_SegComInitTypeDef   LCD_SegCom;

    memset(&LCD_Handle, 0, sizeof(LCD_Handle));

    LCD_Handle.Instance                = LCD;
    LCD_Handle.Init.Bias               = LCD_BIAS_1_3;
    LCD_Handle.Init.Duty               = LCD_DUTY_1_4;
    LCD_Handle.Init.DisplayMode        = LCD_DisplayMode_1;
    LCD_Handle.Init.LCDFrequency       = LCD_LCDFrequency_512HZ;
    LCD_Handle.Init.Driving_Waveform   = LCD_Driving_Waveform_B;
    LCD_Handle.Init.BiasSrc            = LCD_BiasSrc_InRes_Seg31_35_Normal;    //内部电阻模式
//  LCD_Handle.Init.BlinkEN            = LCD_BlinkEN_Enable;                   //闪频使能
    LCD_Handle.Init.BlinkFrequency     = 0x3;                                  //帧间隔时间,影响帧中断时间和LCD DMA请求时间 以及闪烁时间

    HAL_LCD_Init(&LCD_Handle);

    memset(&LCD_InRes, 0, sizeof(LCD_InRes));

    LCD_InRes.Contrast    = LCD_Contrast_903VDD;
    LCD_InRes.BiasRes     = LCD_BiasRes_240k;
    LCD_InRes.FastCharge  = LCD_FastCharge_Enable;
    LCD_InRes.PONTime     = 0x3F;
    LCD_InRes.DriveMod    = LCD_DriveMod_FC;

    HAL_LCD_InResConfig(&LCD_Handle, &LCD_InRes);

    LCD_SegCom.SEG0_31                                      = 0xF0371C00;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEG32_39_COM0_8          = 0xFFFFFFFF;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEGCOM_bit.COM0_3        = 0;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG32_35      = 0xF;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG36_COM7    = 1;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG37_COM6    = 1;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG38_COM5    = 1;
    LCD_SegCom.Stc_SEG32_39_COM0_8.SEGCOM_bit.SEG39_COM4    = 1;

    HAL_LCD_SegComConfig(&LCD_Handle, &LCD_SegCom);

    memset(&GPIOx_Handle, 0, sizeof(GPIOx_Handle));

    GPIOx_Handle.Pin  = GPIO_PIN_0  | GPIO_PIN_4  | GPIO_PIN_8  |
                        GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 |
                        GPIO_PIN_12;	
    GPIOx_Handle.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIOx_Handle);

    GPIOx_Handle.Pin  = GPIO_PIN_0  | GPIO_PIN_11 | GPIO_PIN_12 |
                        GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;	
    GPIOx_Handle.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOB, &GPIOx_Handle);

    GPIOx_Handle.Pin  = GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  |
                        GPIO_PIN_3  | GPIO_PIN_4  | GPIO_PIN_5  |
                        GPIO_PIN_6  | GPIO_PIN_7  | GPIO_PIN_8  |
                        GPIO_PIN_9;	
    GPIOx_Handle.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOC, &GPIOx_Handle);

    GPIOx_Handle.Pin  = GPIO_PIN_5;	
    GPIOx_Handle.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOD, &GPIOx_Handle);

    GPIOx_Handle.Pin       = GPIO_PIN_5;
    GPIOx_Handle.Mode      = GPIO_MODE_OUTPUT_PP;
    GPIOx_Handle.Pull      = GPIO_NOPULL;
    GPIOx_Handle.Alternate = GPIO_FUNCTION_0;
    HAL_GPIO_Init(GPIOA, &GPIOx_Handle);

    GPIOx_Handle.Pin       = GPIO_PIN_15;
    GPIOx_Handle.Mode      = GPIO_MODE_INPUT;
    GPIOx_Handle.Pull      = GPIO_PULLUP;
    GPIOx_Handle.Alternate = GPIO_FUNCTION_0;
    HAL_GPIO_Init(GPIOC, &GPIOx_Handle);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);


    MultiTimerStart(&LCD_MultiTimer, 100, LCD_MultiTimerCallback, "LCD");
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_IRQHandler(void) 
{
    HAL_LCD_IRQHandler(&LCD_Handle);
}

 

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_DisplayNumber1(uint8_t Index, char ch, uint8_t Point)
{
    char TAB[4][8][4] = 
    {
        {"1A ", "1B ", "1C ", "1D ", "1E ", "1F ", "1G ", "1P "},
        {"2A ", "2B ", "2C ", "2D ", "2E ", "2F ", "2G ", "2P "},
        {"3A ", "3B ", "3C ", "3D ", "3E ", "3F ", "3G ", "3P "},
        {"4A ", "4B ", "4C ", "4D ", "4E ", "4F ", "4G ", "---"},
    };

    uint8_t COMn = 0xFF, SEGn = 0xFF;

    uint8_t Code = LCD_SearchCode(ch);

    if(Code != 0xFF)
    {
        for(uint8_t i = 0; i < 7; i++)
        {
            LCD_SearchName(TAB[Index][i], &COMn, &SEGn);

            if((COMn != 0xFF) && (SEGn != 0xFF))
            {
                LCD_WriteBit(COMn, SEGn, (Code >> i) & 0x01);
            }
        }

        LCD_SearchName(TAB[Index][7], &COMn, &SEGn);

        if((COMn != 0xFF) && (SEGn != 0xFF))
        {
            LCD_WriteBit(COMn, SEGn, Point);
        }
    }
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_DisplayNumber2(uint8_t Index, char ch, uint8_t Point)
{
    char TAB[4][8][4] = 
    {
        {"5A ", "5B ", "5C ", "5D ", "5E ", "5F ", "5G ", "5P "},
        {"6A ", "6B ", "6C ", "6D ", "6E ", "6F ", "6G ", "6P "},
        {"7A ", "7B ", "7C ", "7D ", "7E ", "7F ", "7G ", "7P "},
        {"8A ", "8B ", "8C ", "8D ", "8E ", "8F ", "8G ", "---"},
    };

    uint8_t COMn = 0xFF, SEGn = 0xFF;

    uint8_t Code = LCD_SearchCode(ch);

    if(Code != 0xFF)
    {
        for(uint8_t i = 0; i < 7; i++)
        {
            LCD_SearchName(TAB[Index][i], &COMn, &SEGn);

            if((COMn != 0xFF) && (SEGn != 0xFF))
            {
                LCD_WriteBit(COMn, SEGn, (Code >> i) & 0x01);
            }
        }

        LCD_SearchName(TAB[Index][7], &COMn, &SEGn);

        if((COMn != 0xFF) && (SEGn != 0xFF))
        {
            LCD_WriteBit(COMn, SEGn, Point);
        }
    }
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_MultiTimerCallback(MultiTimer *timer, void *userData)
{
    static uint32_t Number1 = 0;
    static uint32_t Number2 = 0;

    Number1 = (Number1 + 1) % 10000;

    if(Number1 < 10)
    {
        LCD_DisplayNumber1(0, ' ', 0);
        LCD_DisplayNumber1(1, ' ', 0);
        LCD_DisplayNumber1(2, '0', 1);
        LCD_DisplayNumber1(3, '0' + Number1, 0);
    }
    else if(Number1 < 100)
    {
        LCD_DisplayNumber1(0, ' ', 0);
        LCD_DisplayNumber1(1, ' ', 0);
        LCD_DisplayNumber1(2, '0' + ((Number1 / 10) % 10), 1);
        LCD_DisplayNumber1(3, '0' + ((Number1 / 1 ) % 10), 0);
    }
    else if(Number1 < 1000)
    {
        LCD_DisplayNumber1(0, ' ', 0);
        LCD_DisplayNumber1(1, '0' + ((Number1 / 100) % 10), 0);
        LCD_DisplayNumber1(2, '0' + ((Number1 / 10 ) % 10), 1);
        LCD_DisplayNumber1(3, '0' + ((Number1 / 1  ) % 10), 0);
    }
    else if(Number1 < 10000)
    {
        LCD_DisplayNumber1(0, '0' + ((Number1 / 1000) % 10), 0);
        LCD_DisplayNumber1(1, '0' + ((Number1 / 100 ) % 10), 0);
        LCD_DisplayNumber1(2, '0' + ((Number1 / 10  ) % 10), 1);
        LCD_DisplayNumber1(3, '0' + ((Number1 / 1   ) % 10), 0);
    }

    Number2 = (Number2 + 1) % 10000;

    if(Number2 < 10)
    {
        LCD_DisplayNumber2(0, ' ', 0);
        LCD_DisplayNumber2(1, ' ', 0);
        LCD_DisplayNumber2(2, '0', 1);
        LCD_DisplayNumber2(3, '0' + Number2, 0);
    }
    else if(Number2 < 100)
    {
        LCD_DisplayNumber2(0, ' ', 0);
        LCD_DisplayNumber2(1, ' ', 0);
        LCD_DisplayNumber2(2, '0' + ((Number2 / 10) % 10), 1);
        LCD_DisplayNumber2(3, '0' + ((Number2 / 1 ) % 10), 0);
    }
    else if(Number2 < 1000)
    {
        LCD_DisplayNumber2(0, ' ', 0);
        LCD_DisplayNumber2(1, '0' + ((Number2 / 100) % 10), 0);
        LCD_DisplayNumber2(2, '0' + ((Number2 / 10 ) % 10), 1);
        LCD_DisplayNumber2(3, '0' + ((Number2 / 1  ) % 10), 0);
    }
    else if(Number2 < 10000)
    {
        LCD_DisplayNumber2(0, '0' + ((Number2 / 1000) % 10), 0);
        LCD_DisplayNumber2(1, '0' + ((Number2 / 100 ) % 10), 0);
        LCD_DisplayNumber2(2, '0' + ((Number2 / 10  ) % 10), 1);
        LCD_DisplayNumber2(3, '0' + ((Number2 / 1   ) % 10), 0);
    }

    MultiTimerStart(&LCD_MultiTimer, 100, LCD_MultiTimerCallback, "LCD");
}

 

实现效果:

不一样的LCD显示实现方式

 

软件工程:

CoreBoard.zip (369.75 KB, 下载次数: 1)
点赞 关注
个人签名We are a team and we work as a team !
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表