前面我们实现了超声距离测量,进一步我们通过LCD1602屏幕来显示测量值。
二. 引脚接线屏幕引脚定义如下
这里使用4位接法

硬件改造如下
VDD接5V
VO接GND
背光5V串2K电阻。
控制信号如下
DB7 DB6 DB5 DB4 E R/W RS
P2_4 P2_3 P2_2 P2_1 P2_6 P1_4 P1_5

添加lcd.C/h文件

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看到精度还是可以的

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