STM32F103学习笔记(4)——LCD段码屏HT1621使用
一、簡(jiǎn)介
HT1621 是 128 點(diǎn) 內(nèi)存映象和多功能的 LCD 驅(qū)動(dòng)器 HT1621 的軟件配置特性使它適用于多種 LCD 應(yīng)用場(chǎng)合包括 LCD 模塊和顯示子系統(tǒng)。用于連接主控制器和 HT1621 的管腳只有 4 或 5 條 HT1621,還有一個(gè)節(jié)電命令用于降低系統(tǒng)功耗。
二、字符顯示原理
液晶管點(diǎn)亮和熄滅原理分別為在對(duì)應(yīng)的RAM地址中寫1和寫0。 首先需要清楚所驅(qū)動(dòng)控制的液晶的COM-SEG對(duì)應(yīng)關(guān)系,然后需要了解HT1621的32×4RAM地址映射。
例如要控制的液晶的裝腳成品圖部分如下:
著重看一個(gè)液晶數(shù)碼管,我們了解原理就行。可以看到圖3中是第2個(gè)液晶數(shù)碼管,有7段,分別為A,B,C,D,E,F,G。也就分別為下面COM\SEG地址對(duì)應(yīng)關(guān)系圖中的2A,2B,2C,2D,2E,2F,2G。
液晶的顯示字符的部分COM公共端輸出口和SEG段輸出口的分布如下表所示,同理我們可以看到例如:2D對(duì)應(yīng)(SEG5,COM0),2E對(duì)應(yīng)(SEG5,COM1),2F對(duì)應(yīng)(SEG5,COM2),2A對(duì)應(yīng)(SEG5,COM3),2C對(duì)應(yīng)(SEG4,COM1),2G對(duì)應(yīng)(SEG4,COM2),2B對(duì)應(yīng)(SEG4,COM3)。
HT1621的RAM 地址映射如下圖所示:
可以清楚的看到要控制液晶段對(duì)應(yīng)SEG號(hào)作為6位地址,COM號(hào)對(duì)應(yīng)作為4位數(shù)據(jù)寫入,此時(shí)注意4位數(shù)據(jù)的高低位。寫數(shù)據(jù)到RAM命令格式為:101+6位RAM地址+4位數(shù)據(jù),其中RAM地址為SEG序號(hào)。
例如我們?cè)趫D3的第二個(gè)液晶數(shù)碼管上顯示數(shù)字,首先我們根據(jù)圖3得到地址映射關(guān)系,先寫入地址SEG4中的四位數(shù)據(jù)(COM3,COM2,COM1,COM0),再寫如地址SEG5中的四位數(shù)據(jù)(COM3,COM2,COM1,COM0),對(duì)應(yīng)關(guān)系如下:
所以如果在圖3中顯示“5”,則在顯示的液晶段對(duì)應(yīng)地址上寫1,不顯示寫0,如下圖所示。所以SEG4地址應(yīng)寫入的數(shù)據(jù)為0110 ,SEG5地址應(yīng)寫入數(shù)據(jù)1101。
三、命令格式
HT1621 可以用軟件設(shè)置 兩種模式的命令可以配置 HT1621 和傳送 LCD 所顯示的數(shù)據(jù)。HT1621 的配置模式稱為命令模式,命令模式類型碼為 100。命令模式包括一個(gè)系統(tǒng)配置命令,一個(gè)系統(tǒng)頻率選擇命令,一個(gè) LCD 配置命令,一個(gè)聲音頻率選擇命令,一個(gè)定時(shí)器/WDT設(shè)置命令和一個(gè)操作命令。數(shù)據(jù)模式包括 READ,WRITE 和 READ-MODIFY-WRITE 操作,下表是數(shù)據(jù)和命令模式類型碼表。
| 操作 | 模式 | 類型碼 |
|---|---|---|
| READ | 數(shù)據(jù) | 110 |
| WRITE | 數(shù)據(jù) | 101 |
| READ-MODIFY-RITE | 數(shù)據(jù) | 101 |
| COMMAND | 命令 | 100 |
模式命令應(yīng)在數(shù)據(jù)或命令傳送前運(yùn)行。如果執(zhí)行連續(xù)的命令,命令模式代碼即 100,將被忽略。當(dāng)系統(tǒng)在不連續(xù)命令模式或不連續(xù)地址數(shù)據(jù)模式下,管腳/CS 應(yīng)設(shè)為 “1” 而且先前的操作模式將復(fù)位。當(dāng)管腳/CS 返回 “0” 時(shí),新的操作模式類型碼應(yīng)先運(yùn)行。
四、時(shí)序圖及程序流程
五、硬件連接
| 功能口 | 引腳 |
|---|---|
| CS | PB.12 |
| DATA | PB.14 |
| WR | PB.13 |
六、移植文件
注意:延時(shí)函數(shù)使用了FreeRTOS的vTaskDelay任務(wù)延時(shí)函數(shù)
鏈接:https://pan.baidu.com/s/1lXWqJIr9Q07al4H3FwNb6Q 提取碼:dsuy
將 board_ht1621.c、board_ht1621.h 兩個(gè)文件加入到工程
6.1 board_ht1621.c
/********************************************************************** INCLUDES*/
#include "FreeRTOS.h"
#include "task.h"#include "board_ht1621.h"static void gpioConfig(void);/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief 初始化LCD屏,HT1621芯片@param 無@return 無
*/
void HT1621_Init(void)
{gpioConfig();vTaskDelay(10);LCD_CS_1();LCD_DATA_1();LCD_WR_1();vTaskDelay(100); // 延時(shí)使LCD工作電壓穩(wěn)定HT1621_WriteCommand(HT1621_SYS_EN); // 打開系統(tǒng)振蕩器HT1621_WriteCommand(HT1621_BIAS); // BIAS 13 4個(gè)公共口HT1621_WriteCommand(HT1621_RC256); // 使用RC_256K系統(tǒng)時(shí)鐘源,片內(nèi)RC振蕩器HT1621_WriteCommand(HT1621_WDT_DIS);HT1621_WriteCommand(HT1621_LCD_ON);
}/**@brief 寫入命令,命令標(biāo)志100@param cmd -[in] 命令數(shù)據(jù)@return 無
*/
void HT1621_WriteCommand(uint8_t cmd)
{uint8_t i;LCD_CS_0(); // CS = 0 vTaskDelay(1);// 寫入命令標(biāo)志,DATA:100LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// Datasheet中命令后的C8為0LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// Datasheet中命令后的C7~C0for(i = 0; i < 8; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((cmd << i) & 0x80){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}LCD_CS_1(); // CS = 1vTaskDelay(1);
}/**@brief 寫入4位數(shù)據(jù),寫入數(shù)據(jù)標(biāo)志101@param addr -[in] 寫入起始地址@param data -[in] 寫入數(shù)據(jù),因?yàn)镠T1621的數(shù)據(jù)位4位,所以實(shí)際寫入數(shù)據(jù)為參數(shù)的后4位@return 無
*/
void HT1621_WriteData4Bit(uint8_t addr, uint8_t data)
{uint8_t i;LCD_CS_0(); // CS = 0 vTaskDelay(1);// 寫入數(shù)據(jù)標(biāo)志,DATA:101LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// 寫入地址,Datasheet中A5~A0for(i = 0; i < 6; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((addr << i) & 0x80){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}// 寫入數(shù)據(jù),Datasheet中D0~D3for(i = 0; i < 4; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((data >> (3 - i)) & 0x01){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}LCD_CS_1(); // CS = 1vTaskDelay(1);
}/**@brief 寫入8位數(shù)據(jù),寫入數(shù)據(jù)標(biāo)志101@param addr -[in] 寫入起始地址@param data -[in] 寫入數(shù)據(jù)@return 無
*/
void HT1621_WriteData8Bit(uint8_t addr, uint8_t data)
{uint8_t i;LCD_CS_0(); // CS = 0 vTaskDelay(1);// 寫入數(shù)據(jù)標(biāo)志,DATA:101LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// 寫入地址,Datasheet中A5~A0for(i = 0; i < 6; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((addr << i) & 0x80){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}// 寫入數(shù)據(jù),Datasheet中兩組D0~D3for(i = 0; i < 8; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((data >> (7 - i)) & 0x01){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}LCD_CS_1(); // CS = 1vTaskDelay(1);
}/********************************************************************** LOCAL FUNCTIONS*/
/**@brief 引腳初始化@param 無@return 無
*/
static void gpioConfig(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(HT1621_CS_CLK|HT1621_DATA_CLK|HT1621_WR_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = HT1621_CS_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(HT1621_CS_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = HT1621_DATA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(HT1621_DATA_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = HT1621_WR_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(HT1621_WR_PORT, &GPIO_InitStructure);
}/****************************************************END OF FILE****************************************************/
6.2 board_ht1621.h
#ifndef _BOARD_HT1621_H_
#define _BOARD_HT1621_H_/********************************************************************** INCLUDES*/
#include "stm32f10x.h"/********************************************************************** DEFINITIONS*/
#define HT1621_CS_PORT GPIOB // GPIO端口
#define HT1621_CS_CLK RCC_APB2Periph_GPIOB // GPIO端口時(shí)鐘
#define HT1621_CS_PIN GPIO_Pin_12 // 定義HT1621的CS管腳#define HT1621_DATA_PORT GPIOB // GPIO端口
#define HT1621_DATA_CLK RCC_APB2Periph_GPIOB // GPIO端口時(shí)鐘
#define HT1621_DATA_PIN GPIO_Pin_14 // 定義HT1621的DATA管腳#define HT1621_WR_PORT GPIOB // GPIO端口
#define HT1621_WR_CLK RCC_APB2Periph_GPIOB // GPIO端口時(shí)鐘
#define HT1621_WR_PIN GPIO_Pin_13 // 定義HT1621的WR管腳#define LCD_CS_0() GPIO_ResetBits(HT1621_CS_PORT, HT1621_CS_PIN)
#define LCD_CS_1() GPIO_SetBits(HT1621_CS_PORT, HT1621_CS_PIN)
#define LCD_DATA_0() GPIO_ResetBits(HT1621_DATA_PORT, HT1621_DATA_PIN)
#define LCD_DATA_1() GPIO_SetBits(HT1621_DATA_PORT, HT1621_DATA_PIN)
#define LCD_WR_0() GPIO_ResetBits(HT1621_WR_PORT, HT1621_WR_PIN)
#define LCD_WR_1() GPIO_SetBits(HT1621_WR_PORT, HT1621_WR_PIN)#define COMMAND_CODE 0x80 // 命令碼
#define WRITE_DATA_CODE 0xA0 // 寫命令#define HT1621_BIAS 0x52 // 1/3duty 4com
#define HT1621_SYS_DIS 0x00 // 關(guān)振系統(tǒng)蕩器和LCD偏壓發(fā)生器
#define HT1621_SYS_EN 0x02 // 打開系統(tǒng)振蕩器
#define HT1621_LCD_OFF 0x04 // 關(guān)閉LCD偏壓
#define HT1621_LCD_ON 0x06 // 打開LCE偏壓
#define HT1621_XTAL 0x28 // 外部接時(shí)鐘
#define HT1621_RC256 0x30 // 內(nèi)部時(shí)鐘
#define HT1621_WDT_DIS 0X0A // 關(guān)閉看門狗
#define HT1621_TONE_ON 0x12 // 打開聲音輸出
#define HT1621_TONE_OFF 0x10 // 關(guān)閉聲音輸出/********************************************************************** API FUNCTIONS*/
void HT1621_Init(void);
void HT1621_WriteCommand(uint8_t cmd);
void HT1621_WriteData4Bit(uint8_t addr, uint8_t data);
void HT1621_WriteData8Bit(uint8_t addr, uint8_t data);#endif /* _BOARD_HT1621_H_ */
七、使用例子
/********************************************************************** DEFINITIONS*/
#define TEMP_ADDR 0x00
#define FOURTH_8_MHz_ADDR 0x04
#define FOURTH_8_ADDR 0x08
#define THIRD_8_75us_ADDR 0x0C
#define THIRD_8_ADDR 0x10
#define SECOND_8_POINT_ADDR 0x14
#define SECOND_8_ADDR 0x18
#define FIRST_8_50us_ADDR 0x1C
#define FIRST_8_ADDR 0x20
#define FM_SOUND_1_ADDR 0x24
#define SIGNAL_ADDR 0x28#define DISPLAY_ALARM 0x03
#define DISPLAY_FM 0x04
#define DISPLAY_1_1 0x08
#define DISPLAY_MHZ 0x10HT1621_Init();
HT1621_WriteData4Bit(TEMP_ADDR, 0x00); // ℃滅
HT1621_WriteData4Bit(SIGNAL_ADDR, 0x00); // 信號(hào)滅
HT1621_WriteData4Bit(FM_SOUND_1_ADDR, DISPLAY_ALARM | DISPLAY_FM); // 報(bào)警+FM亮
HT1621_WriteData8Bit(FOURTH_8_MHz_ADDR, DISPLAY_MHZ); // MHz亮/**@brief LCD屏顯示頻率@param frequency -[in] 頻率@return 無
*/
void LCD_ShowFrequency(uint32 frequency)
{calculateHundreds(frequency); // 百位calculateTens(frequency); // 十位calculateOnes(frequency); // 個(gè)位calculateDecimals(frequency); // 小數(shù)位
}/**@brief 計(jì)算頻率百位,如87.5MHz,則百位0@param frequency -[in] 頻率@return 無
*/
static void calculateHundreds(uint32 frequency)
{if(frequency / 100000 == 1){s_alarm |= DISPLAY_1_1;HT1621_WriteData4Bit(FM_SOUND_1_ADDR, s_alarm); // 1亮}else{s_alarm &= 0x07;HT1621_WriteData4Bit(FM_SOUND_1_ADDR, s_alarm); // 1滅}
}/**@brief 計(jì)算頻率十位,如87.5MHz,則十位8@param frequency -[in] 頻率@return 無
*/
static void calculateTens(uint32 frequency)
{if(frequency / 10000 % 10 == 0){HT1621_WriteData8Bit(FIRST_8_50us_ADDR, 0xAF); // 0}else if(frequency / 10000 % 10 == 8){HT1621_WriteData8Bit(FIRST_8_50us_ADDR, 0xEF); // 8}else if(frequency / 10000 % 10 == 9){HT1621_WriteData8Bit(FIRST_8_50us_ADDR, 0xED); // 9}
}/**@brief 計(jì)算頻率個(gè)位,如87.5MHz,則個(gè)位7@param frequency -[in] 頻率@return 無
*/
static void calculateOnes(uint32 frequency)
{if(frequency / 1000 % 10 == 0){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xBF); // 0.}else if(frequency / 1000 % 10 == 1){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xB0); // 1.}else if(frequency / 1000 % 10 == 2){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xDB); // 2.} else if(frequency / 1000 % 10 == 3){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xF9); // 3.} else if(frequency / 1000 % 10 == 4){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xF4); // 4.}else if(frequency / 1000 % 10 == 5){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0x7D); // 5.}else if(frequency / 1000 % 10 == 6){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0x7F); // 6.}else if(frequency / 1000 % 10 == 7){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xB8); // 7.}else if(frequency / 1000 % 10 == 8){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xFF); // 8.}else if(frequency / 1000 % 10 == 9){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xFD); // 9.}
}/**@brief 計(jì)算頻率小數(shù)位,如87.5MHz,則小數(shù)位5@param frequency -[in] 頻率@return 無
*/
static void calculateDecimals(uint32 frequency)
{if(frequency / 100 % 10 == 0){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xAF); // 0}else if(frequency / 100 % 10 == 1){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xA0); // 1}else if(frequency / 100 % 10 == 2){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xCB); // 2} else if(frequency / 100 % 10 == 3){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xE9); // 3} else if(frequency / 100 % 10 == 4){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xE4); // 4}else if(frequency / 100 % 10 == 5){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0x6D); // 5}else if(frequency / 100 % 10 == 6){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0x6F); // 6}else if(frequency / 100 % 10 == 7){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xA8); // 7}else if(frequency / 100 % 10 == 8){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xEF); // 8}else if(frequency / 100 % 10 == 9){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xED); // 9}
}
? 由 Leung 寫于 2020 年 7 月 14 日
? 參考:STM32液晶顯示HT1621驅(qū)動(dòng)原理及程序代碼
HT1621B段碼 LCD屏驅(qū)動(dòng) 51單片機(jī)驅(qū)動(dòng)程序
HT1621測(cè)試程序
總結(jié)
以上是生活随笔為你收集整理的STM32F103学习笔记(4)——LCD段码屏HT1621使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客题霸 [进制转换] C++题解/答案
- 下一篇: Acronis Disk Directo