这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【let'sdo|2026年第2期】LCD1602显示超声测量距离

共2条 1/1 1 跳转至

【let'sdo|2026年第2期】LCD1602显示超声测量距离

菜鸟
2026-08-11 10:22:24     打赏
一. 前言

前面我们实现了超声距离测量,进一步我们通过LCD1602屏幕来显示测量值。 

二. 引脚接线

屏幕引脚定义如下image.png

这里使用4位接法

image.png

硬件改造如下

VDD5V

VOGND

背光5V2K电阻。

控制信号如下

 DB7  DB6  DB5  DB4  E    R/W      RS

 P2_4  P2_3 P2_2  P2_1 P2_6  P1_4     P1_5

image.png

三. 驱动

添加lcd.C/h文件

image.png

IO初始化,可以线诸葛翻转IO测试IO是都输出正确

/*
 DB7  DB6  DB5  DB4  E    R/W      RS
 P2_4 P2_3 P2_2 P2_1 P2_6 P1_4     P1_5
0:WRITE  0:CMD
1:READ  1:DATA
 */
#define LCD_DB7_PORT PORT2
#define LCD_DB7_PORT_PIN  4U
#define LCD_DB7_GPIO GPIO2              
#define LCD_DB7_GPIO_PIN 4U            
 
#define LCD_DB6_PORT PORT2
#define LCD_DB6_PORT_PIN  3U
#define LCD_DB6_GPIO GPIO2              
#define LCD_DB6_GPIO_PIN 3U  
 
#define LCD_DB5_PORT PORT2
#define LCD_DB5_PORT_PIN  2U
#define LCD_DB5_GPIO GPIO2              
#define LCD_DB5_GPIO_PIN 2U  
 
#define LCD_DB4_PORT PORT2
#define LCD_DB4_PORT_PIN  1U
#define LCD_DB4_GPIO GPIO2              
#define LCD_DB4_GPIO_PIN 1U  
 
#define LCD_E_PORT PORT2
#define LCD_E_PORT_PIN  6U
#define LCD_E_GPIO GPIO2              
#define LCD_E_GPIO_PIN 6U  
 
#define LCD_RW_PORT PORT1
#define LCD_RW_PORT_PIN  4U
#define LCD_RW_GPIO GPIO1              
#define LCD_RW_GPIO_PIN 4U  
 
#define LCD_RS_PORT PORT1
#define LCD_RS_PORT_PIN  5U
#define LCD_RS_GPIO GPIO1              
#define LCD_RS_GPIO_PIN 5U  
 
 
const gpio_pin_config_t pin_config = {
        .pinDirection = kGPIO_DigitalOutput,
        .outputLogic = 1U
};

const port_pin_config_t port_pin = {/* Internal pull-up/down resistor is disabled */
                                       kPORT_PullDisable,
                                       /* Low internal pull resistor value is selected. */
                                       kPORT_LowPullResistor,
                                       /* Fast slew rate is configured */
                                       kPORT_FastSlewRate,
                                       /* Passive input filter is disabled */
                                       kPORT_PassiveFilterDisable,
                                       /* Open drain output is disabled */
                                       kPORT_OpenDrainDisable,
                                       /* Low drive strength is configured */
                                       kPORT_LowDriveStrength,
                                       /* Normal drive strength is configured */
                                       kPORT_NormalDriveStrength,
                                       /* Pin is configured as P3_12 */
                                       kPORT_MuxAlt0,
                                       /* Digital input enabled */
                                       kPORT_InputBufferEnable,
                                       /* Digital input is not inverted */
                                       kPORT_InputNormal,
                                       /* Pin Control Register fields [15:0] are not locked */
                                       kPORT_UnlockRegister};

void lcd_gpio_init(void) 
{
    CLOCK_EnableClock(kCLOCK_GateGPIO2);
  CLOCK_EnableClock(kCLOCK_GatePORT2);
  RESET_ReleasePeripheralReset(kGPIO2_RST_SHIFT_RSTn);
  RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn);
    CLOCK_EnableClock(kCLOCK_GateGPIO1);
  CLOCK_EnableClock(kCLOCK_GatePORT2);
  RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn);
  RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn);
 
    GPIO_PinInit(LCD_DB7_GPIO, LCD_DB7_GPIO_PIN, &pin_config);
    GPIO_PinInit(LCD_DB6_GPIO, LCD_DB6_GPIO_PIN, &pin_config);
    GPIO_PinInit(LCD_DB5_GPIO, LCD_DB5_GPIO_PIN, &pin_config);
    GPIO_PinInit(LCD_DB4_GPIO, LCD_DB4_GPIO_PIN, &pin_config); 
    GPIO_PinInit(LCD_E_GPIO, LCD_E_GPIO_PIN, &pin_config);
    GPIO_PinInit(LCD_RW_GPIO, LCD_RW_GPIO_PIN, &pin_config);
    GPIO_PinInit(LCD_RS_GPIO, LCD_RS_GPIO_PIN, &pin_config);

    PORT_SetPinConfig(LCD_DB7_PORT, LCD_DB7_PORT_PIN, &port_pin);
    PORT_SetPinConfig(LCD_DB6_PORT, LCD_DB6_PORT_PIN, &port_pin);
    PORT_SetPinConfig(LCD_DB5_PORT, LCD_DB5_PORT_PIN, &port_pin);
    PORT_SetPinConfig(LCD_DB4_PORT, LCD_DB4_PORT_PIN, &port_pin);
    PORT_SetPinConfig(LCD_E_PORT, LCD_E_PORT_PIN, &port_pin);
    PORT_SetPinConfig(LCD_RW_PORT, LCD_RW_PORT_PIN, &port_pin);
    PORT_SetPinConfig(LCD_RS_PORT, LCD_RS_PORT_PIN, &port_pin);

#if 0
while(1){
GPIO_PortClear(LCD_E_GPIO, 1u << LCD_E_GPIO_PIN);
GPIO_PortClear(LCD_RS_GPIO, 1u << LCD_RS_GPIO_PIN);
GPIO_PortClear(LCD_RW_GPIO, 1u << LCD_RW_GPIO_PIN);
GPIO_PortClear(LCD_DB4_GPIO, 1u << LCD_DB4_GPIO_PIN);
GPIO_PortClear(LCD_DB5_GPIO, 1u << LCD_DB5_GPIO_PIN);
GPIO_PortClear(LCD_DB6_GPIO, 1u << LCD_DB6_GPIO_PIN);
GPIO_PortClear(LCD_DB7_GPIO, 1u << LCD_DB7_GPIO_PIN);
GPIO_PortSet(LCD_E_GPIO, 1u << LCD_E_GPIO_PIN);
GPIO_PortSet(LCD_RS_GPIO, 1u << LCD_RS_GPIO_PIN);
GPIO_PortSet(LCD_RW_GPIO, 1u << LCD_RW_GPIO_PIN);
GPIO_PortSet(LCD_DB4_GPIO, 1u << LCD_DB4_GPIO_PIN);
GPIO_PortSet(LCD_DB5_GPIO, 1u << LCD_DB5_GPIO_PIN);
GPIO_PortSet(LCD_DB6_GPIO, 1u << LCD_DB6_GPIO_PIN);
GPIO_PortSet(LCD_DB7_GPIO, 1u << LCD_DB7_GPIO_PIN);
}
#endif
}

IO操作接口

void lcd_set_e(uint8_t level) 
{
if (level) {
GPIO_PortSet(LCD_E_GPIO, 1u << LCD_E_GPIO_PIN);
} else {
GPIO_PortClear(LCD_E_GPIO, 1u << LCD_E_GPIO_PIN);
}
}
 
void lcd_set_rs(uint8_t level) 
{
if (level) {
GPIO_PortSet(LCD_RS_GPIO, 1u << LCD_RS_GPIO_PIN);
} else {
GPIO_PortClear(LCD_RS_GPIO, 1u << LCD_RS_GPIO_PIN);
}
}
 
void lcd_set_rw(uint8_t level) 
{
if (level) {
GPIO_PortSet(LCD_RW_GPIO, 1u << LCD_RW_GPIO_PIN);
} else {
GPIO_PortClear(LCD_RW_GPIO, 1u << LCD_RW_GPIO_PIN);
}
}
 
void lcd_set_db(uint8_t val) 
{
if (val &0x10) {
GPIO_PortSet(LCD_DB4_GPIO, 1u << LCD_DB4_GPIO_PIN);
} else {
GPIO_PortClear(LCD_DB4_GPIO, 1u << LCD_DB4_GPIO_PIN);
}
if (val &0x20) {
GPIO_PortSet(LCD_DB5_GPIO, 1u << LCD_DB5_GPIO_PIN);
} else {
GPIO_PortClear(LCD_DB5_GPIO, 1u << LCD_DB5_GPIO_PIN);
}
if (val &0x40) {
GPIO_PortSet(LCD_DB6_GPIO, 1u << LCD_DB6_GPIO_PIN);
} else {
GPIO_PortClear(LCD_DB6_GPIO, 1u << LCD_DB6_GPIO_PIN);
}
if (val &0x80) {
GPIO_PortSet(LCD_DB7_GPIO, 1u << LCD_DB7_GPIO_PIN);
} else {
GPIO_PortClear(LCD_DB7_GPIO, 1u << LCD_DB7_GPIO_PIN);
}
}
 
void lcd_delay(uint32_t delay)
{
timer_freetimer_delayus(delay*1000);
}

驱动,其中lcd_dis_str显示字符串

void lcd_nybble(void)
{
lcd_set_e(1);
lcd_delay(1); //enable pulse width >= 300ns
lcd_set_e(0); //Clock enable: falling edge
}
 
void lcd_command(uint8_t i)
{
lcd_set_db(i); //put data on output Port
lcd_set_rs(0); //D/I=LOW : send instruction
lcd_set_rw(0); //R/W=LOW : Write
lcd_nybble(); //Send upper 4 bits
i = i<<4;//Shift over by 4 bits
lcd_set_db(i); //put data on output Port
lcd_nybble(); //Send upper 4 bits
}
 
void lcd_write(uint8_t i)
{
lcd_set_db(i); //put data on output Port
lcd_set_rs(1); //D/I=HIGH : send data
lcd_set_rw(0); //R/W=LOW : Write
lcd_nybble(); //Clock upper 4 bits
i = i<<4;//Shift over by 4 bits
lcd_set_db(i); //put data on output Port
lcd_nybble();//Clock upper 4 bits
}
 
void lcd_init(void)
{
lcd_gpio_init();

lcd_set_db(0);
lcd_set_e(0);
lcd_set_rs(0);  //0:CMD
lcd_set_rw(0);  //0:WRITE
 
lcd_delay(100); //Wait >40 msec after power is applied
lcd_set_db(0x30); //put 0x30 on the output port
lcd_delay(30); //must wait 5ms, busy flag not available
lcd_nybble(); //command 0x30 = Wake up
lcd_delay(10); //must wait 160us, busy flag not available
lcd_nybble(); //command 0x30 = Wake up #2
lcd_delay(10); //must wait 160us, busy flag not available
lcd_nybble(); //command 0x30 = Wake up #3
lcd_delay(10); //can check busy flag now instead of delay
/*
Function Set 0 0 0 0 1 DL      N        F x x
                       0:4bit  0:1-line 0:5x8dots
                       1:8bit  1:2-line 0:5x11dots
*/
lcd_set_db(0x20); //put 0x20 on the output port
lcd_nybble(); //Function set: 4-bit interface

lcd_command(0x28); //Function set: 4-bit/2-line

/*
  Cursor or Display Shift 0 0 0 0 0 1 S/C                                 R/L            x x
                                    0:                                  0:Shift left
                                    1: Cursor follows the display shift 1:Shift right
*/
lcd_command(0x10); //Set cursor
/*
 Display ON/OFF 0 0 0 0 0 0 1 D            C           B
                              0:           0:          0:   
                              1:display on 1:cursor on 1:cursor position on
 */
lcd_command(0x0F); //Display ON; Blinking cursor
/*
 *Entry Mode Set 0 0 0 0 0 0 0 1 I/D                          S
 0:Decrement of DDRAM address 0:
                                 1:Increment of DDRAM address 1:Shift of entire display
 */
lcd_command(0x06); //Entry Mode set
}
 
void lcd_write_cgram(uint8_t pos, char* c, uint8_t len)
{
lcd_command(0x40 | (pos&0x3F)); 
for(uint8_t i=0; i<len; i++){
lcd_write(c[i]);
}
}
 
void lcd_write_ddram(uint8_t pos, char* c, uint8_t len)
{
lcd_command(0x80 | (pos&0x7F)); 
for(uint8_t i=0; i<len; i++){
lcd_write(c[i]);
}
}
 
void lcd_dis_char(uint8_t pos, char c)
{
char tmp = c;
lcd_write_ddram(pos, &tmp, 1);
}
 
void lcd_dis_str(uint8_t pos, char* c)
{
lcd_write_ddram(pos, c, strlen(c));
}
四. 测试

int main(void)
{
    char ch;
 
    /* Init board hardware. */
    BOARD_InitHardware();
 
    PRINTF("MCUX SDK version: %s\r\n", MCUXSDK_VERSION_FULL_STR);
 
    PRINTF("hello world.\r\n");
 
gpio_init();
  timer_freetimer_init();
capture_init();
  //capture_start();
gpio_trig_set(0);
lcd_init();
    while (1)
    {
int distance = get_distance();
  if(distance < 0) {
PRINTF("get distance err\r\n");
} else {
distance = distance*340/(2*1000);
snprintf(distance_str,sizeof(distance_str),"%dmm",distance);
PRINTF("distance:%smm\r\n", distance_str);
lcd_dis_str(0, distance_str);
}
  timer_freetimer_delayus(1000000);
    }
}

使用一把30CM的尺子定一个距离

实测如下,303mm看到精度还是可以的

image.png

五. 总结

 

以上就实现了超声距离采集并通过屏幕显示, 实现了一个简单的超声测距仪。





关键词: LCD1602    

助工
2026-08-11 10:55:32     打赏
2楼

这种并口接线的方式是不是只能使用GPIO模拟的方式来实现了啊?


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]