STM32L152单片机驱动段码LCD屏,HAL_LCD_Init函数执行失败,卡在LCD_FLAG_RDY里面,函数返回HAL_TIMEOUT

/*!< Wait Until the LCD Booster is ready */
while(__HAL_LCD_GET_FLAG(hlcd, LCD_FLAG_RDY) == RESET)
{if((HAL_GetTick() - tickstart ) > LCD_TIMEOUT_VALUE){   hlcd->ErrorCode = HAL_LCD_ERROR_RDY;  return HAL_TIMEOUT;}
}

也就是LCD初始化过程中,LCD_SR_RDY位始终为0,这表明电压调节器不能正常工作。

在STM32L152单片机中,LCD和RTC是共用一个时钟。CubeMX生成的LCD初始化代码里面,选择LCD时钟的代码如下:

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LCD;
PeriphClkInit.LCDClockSelection = RCC_RTCCLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{Error_Handler();
}

然而点进HAL_RCCEx_PeriphCLKConfig函数一看,函数里面只有下面这句话:

__HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);

也就是说根本就没有用到LCDClockSelection这个成员,库里面实际使用的是RTCClockSelection成员
调试程序也会发现,RCC_CSR_RTCSEL为0x00,没有设置为0x02,LCD外设根本就没有得到LSI时钟!

所以代码应该改成

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);

这样LCD时钟才能选择成功,问题就解决了。

这完完全全是HAL库的BUG导致的问题

另外,LCD选择的是内部参考电压(LCD_VOLTAGESOURCE_INTERNAL),所以VLCD引脚上接的是1μF的电容到GND。VLCD引脚没有接VCC。

【完整代码】

#include <stm32l1xx.h>
#include "common.h"
#include "LCDSEG.h"#define LCDSEG_A 0x80
#define LCDSEG_B 0x40
#define LCDSEG_C 0x20
#define LCDSEG_D 0x10
#define LCDSEG_E 0x08
#define LCDSEG_F 0x04
#define LCDSEG_G 0x02#define LCDSEG_TABLE_L 0x1c
#define LCDSEG_TABLE_O lcdseg_table[0]
#define LCDSEG_TABLE_H 0x6e
#define LCDSEG_TABLE_I 0x0cconst static uint8_t lcdseg_table[10] = {0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6};LCD_HandleTypeDef hlcd;void LCDSEG_DisplayBatteryIcon(int enabled)
{HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0x32d, (enabled) ? _BV(4) : 0);HAL_LCD_UpdateDisplayRequest(&hlcd);
}void LCDSEG_DisplayBuzzerIcon(int enabled)
{HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0x13d, (enabled) ? _BV(9) : 0);HAL_LCD_UpdateDisplayRequest(&hlcd);
}void LCDSEG_DisplayTemperature(double temp)
{int num;uint16_t seg[3];uint32_t output[3] = {0};num = (int)((temp + 0.05) * 10); // 保留一位小数, 四舍五入if (num >= 0 && num <= 999){seg[0] = lcdseg_table[num / 100]; // 十位seg[1] = lcdseg_table[num % 100 / 10]; // 个位seg[2] = lcdseg_table[num % 10]; // 十分位output[0] |= _BV(3); // 小数点}else{seg[0] = 0;if (num < 0){seg[1] = LCDSEG_TABLE_L;seg[2] = LCDSEG_TABLE_O;}else{seg[1] = LCDSEG_TABLE_H;seg[2] = LCDSEG_TABLE_I;}}if (seg[0] & LCDSEG_D)output[0] |= _BV(8);if (seg[1] & LCDSEG_D)output[0] |= _BV(5);if (seg[2] & LCDSEG_D)output[0] |= _BV(2);if (seg[0] & LCDSEG_E)output[1] |= _BV(9);if (seg[0] & LCDSEG_G)output[1] |= _BV(8);if (seg[0] & LCDSEG_C)output[1] |= _BV(7);if (seg[1] & LCDSEG_E)output[1] |= _BV(6);if (seg[1] & LCDSEG_G)output[1] |= _BV(5);if (seg[1] & LCDSEG_C)output[1] |= _BV(4);if (seg[2] & LCDSEG_E)output[1] |= _BV(3);if (seg[2] & LCDSEG_G)output[1] |= _BV(2);if (seg[2] & LCDSEG_C)output[1] |= _BV(1);if (seg[0] & LCDSEG_F)output[2] |= _BV(9);if (seg[0] & LCDSEG_A)output[2] |= _BV(8);if (seg[0] & LCDSEG_B)output[2] |= _BV(7);if (seg[1] & LCDSEG_F)output[2] |= _BV(6);if (seg[1] & LCDSEG_A)output[2] |= _BV(5);if (seg[1] & LCDSEG_B)output[2] |= _BV(4);if (seg[2] & LCDSEG_F)output[2] |= _BV(3);if (seg[2] & LCDSEG_A)output[2] |= _BV(2);if (seg[2] & LCDSEG_B)output[2] |= _BV(1);HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0x211, output[0]);HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER2, 0x01, output[1]);HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER4, 0x01, output[2]);HAL_LCD_UpdateDisplayRequest(&hlcd);
}void LCDSEG_EnableBackground(int enabled)
{HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, (enabled) ? GPIO_PIN_RESET : GPIO_PIN_SET);
}void LCDSEG_Init(void)
{GPIO_InitTypeDef gpio;RCC_OscInitTypeDef osc;RCC_PeriphCLKInitTypeDef periph_clock;__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_LCD_CLK_ENABLE();// 选择LCD时钟为LSIosc.OscillatorType = RCC_OSCILLATORTYPE_LSI;osc.LSIState = RCC_LSI_ON;osc.PLL.PLLState = RCC_PLL_NONE;HAL_RCC_OscConfig(&osc);periph_clock.PeriphClockSelection = RCC_PERIPHCLK_RTC;periph_clock.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;HAL_RCCEx_PeriphCLKConfig(&periph_clock);// PA1~3: LCD_SEG0~2, PA6~7: LCD_SEG3~4, PA8~10: LCD_COM0~2gpio.Alternate = GPIO_AF11_LCD;gpio.Mode = GPIO_MODE_AF_PP;gpio.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;gpio.Pull = GPIO_NOPULL;gpio.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &gpio);// PB0~1: LCD_SEG5~6, PB3~5: LCD_SEG7~9, PB10~13: LCD_SEG10~13gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;HAL_GPIO_Init(GPIOB, &gpio);// 背光引脚LCDSEG_EnableBackground(0); // 暂不开背光gpio.Mode = GPIO_MODE_OUTPUT_PP;gpio.Pin = GPIO_PIN_14;gpio.Pull = GPIO_NOPULL;gpio.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOC, &gpio);hlcd.Instance = LCD;hlcd.Init.Bias = LCD_BIAS_1_3; // 电平个数hlcd.Init.Contrast = LCD_CONTRASTLEVEL_3; // 最高电压hlcd.Init.Divider = LCD_DIVIDER_27;hlcd.Init.Duty = LCD_DUTY_1_3; // COM公共端个数hlcd.Init.Prescaler = LCD_PRESCALER_16;HAL_LCD_Init(&hlcd);// 显示P2~4HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0, 0x01);HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER2, 0, 0x01);HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER4, 0, 0x01);HAL_LCD_UpdateDisplayRequest(&hlcd);
}

【解决方案】STM32L152单片机驱动段码LCD屏,执行HAL_LCD_Init函数失败返回HAL_TIMEOUT,长时间卡在LCD_FLAG_RDY的while循环里面的解决办法相关推荐

  1. 段码LCD研究 | 用HT1621B驱动段码LCD屏

    [本文发布地址https://blog.csdn.net/Stack_/article/details/117532877,未经许可不得转载,转载须注明出处] 一.探索 这是一个从乐心血压计上拆下来的 ...

  2. stm32驱动lcd段码io配置_LCD驱动型单片机与段码液晶屏配合使用参考

    电子产品的开发自然少不了电子工程师的参与,他们是功能的主要实现者,那么对于之前没有接触和使用过LCD液晶屏的电子工程师来说,使用了LCD液晶屏的新产品要提前先了解LCD液晶屏的相关知识之后才能实现连接 ...

  3. ht1621b和单片机电平匹配_HT1621B驱动段码液晶屏参考程序——晶拓液晶屏

    (1)    段码屏的驱动程序跟数码管的静态驱动程序一样,只要我们弄懂了怎样显示一个基本单位,根据此基本单位编写一个字库表,然后   用与(&)和或(|)这两种位运算符就可以随心所欲编写我们要 ...

  4. 如何驱动段码液晶屏?

    日常生活中我见的较多的就是段码液晶屏了,如遥控器.冰箱.电子体温计.设备上的显示器等等,段码屏应用如此广泛主要是它即有着普通数码管的特征,又有着点阵液晶屏的特征:有固定的图形,不但成本低而且又美观.那 ...

  5. DSP28035驱动HT1621B显示段码LCD屏

    最近做的项目里面使用的控制芯片为TI公司的28035,在控制程序以外,需要用该芯片控制显示LCD屏幕,其中驱动LCD屏幕的是HT1621B芯片,由于这也是我第一次写驱动LCD的程序以及第一次接触162 ...

  6. M-Arch(雅特力M4)【AT-START-F425测评】No.06 驱动段码LCD

    前言 还是之前折腾GD32L233时弄的一块SLCD屏,改吧改吧就在AT32F425上跑起来了. 板子其实比较简单,打板如下: SLCD板 其中: 信号管脚RC参数中的R参数以及VLCD的分压电阻可直 ...

  7. M-Arch(番外14)GD32L233评测-驱动段码LCD

    前言 之前粗看GD32L233的资料,支持SLCD驱动,高兴的买了一块裸屏: 结果后来细看,发现CCT6不支持,裸屏不能浪费了,又买了一块天微的TM1621D驱动,自己折腾了一块SLCD板,板子其实比 ...

  8. HT1621B段码 LCD屏驱动 51单片机驱动程序

    逻辑图 左边三段数字是温度显示 右边两位是湿度 下面是完整的程序 (io口模拟spi发送数据写给ram)个人理解 水平有限 头文件 lcd.h #ifndef __LCD__H__ #define _ ...

  9. STC8a8K单片机c语言驱动彩屏,用STC单片机驱动笔段式LCD屏

    #include//接口定义 //1602的数据接口为P0 sbit RSPIN = P2^0; sbit RWPIN = P2^1; sbit EPIN =  P2^2; unsigned char ...

最新文章

  1. matlab正态分布
  2. 如何在Flexbox中垂直对齐文本?
  3. hadoop实战二 单机部署2
  4. 任务栏托盘不消失的问题-有启示
  5. C - 数据结构实验之排序三:bucket sort(水题)
  6. 一个基于 Spring Boot 的项目骨架,拿走即用
  7. 配置MGR时修改了/etc/hosts但映射后的hostname不起作用
  8. 算法导论笔记:06堆排序
  9. visual studio code搭建本地服务器(node.js+express)
  10. C语言中递归什么时候能够省略return引发的思考:通过内联汇编解读C语言函数return的本质...
  11. 前端学习(2136):使用es6模块化出现Access to script at ‘file:///... ..from origin ‘null‘ has been blocked。。。错误
  12. 极狐(GitLab)发布首款“GitNative”DevOps云一体化解决方案
  13. html文字竖直书写,css 文字竖直居中的写法和图片垂直居中代码(图文)
  14. elasticsearch x-pack license过期
  15. java多状态机_一个java状态机样例的代码
  16. Javascript第二章中While/do..while循环第三课
  17. Linux下安装DB2_v9.7详细教程
  18. 2-机器学习入门-读书笔记
  19. 磁盘阵列卡 远程监控(MegaRAID Storage Manager)(一)
  20. 图像影音型计算机主板选择什么,开启4K新时代 七款家用影音主板推荐

热门文章

  1. 燃气管道运行全局实时监控系统-海城支线总页面
  2. 最全的的初中数学公式大全
  3. 树模型(一):预备知识
  4. 你等的最新版代码管理它来了,代码管理 Codeup概述(新版)
  5. 凡拓数字通过注册:年营收7亿 伍穗颖夫妇控制43%股权
  6. html自动循环播放视频列表
  7. 掌握动效设计!让你的设计富有未来科技感(上)
  8. word@tips官方文档和教程@软件界面介绍@功能区自定义@拼写检查@AI润色改进@ 图片顶部上方插入文字
  9. TResNet学习笔记 --- TResNet: High Performance GPU-Dedicated Architecture
  10. Cisco交换机与路由器常用协议及其配置命令