无线串口模块,LCD1602模块
lcd1602
看一个项目里有PCF8574 和 HD44780,我好奇,板子上又没有,这是干嘛的, 问AI,是一种lcd1602模块,长这个样子
好处, 只需要四根线就可以让任何板子有个小显示屏.
使用IIC通信, 固定使用PB6,PB7两个引脚 (我的板子), 街上这两个,和3.3v和gnd就可以工作了.
引入步骤 keil:
- copy2个文件到
E:\keil_v5_git_workspace\lcd1602_test\App\lcd - 在keil里add这2个文件 ‘pcf8574_std.c’,‘pcf8574_std.h’
- keil里魔法棒 include path加 lcd
- main.c里加#include “pcf8574_std.h”
- stdPeriph-driver里引入 stm32f10x_i2c.c
- main.c里加
LCD1602_Init(); // 屏初始化
LCD1602_ShowStr(0, 0, “STM32 Standard”);
LCD1602_ShowStr(0, 1, “LCD1602 I2C OK”);
pcf8574_std.h
#ifndef __PCF8574_H
#define __PCF8574_H
#include "stm32f10x.h" // 标准库核心头文件
// PCF8574 I2C 地址(根据硬件修改,常见 0x27 / 0x3F)
#define PCF8574_ADDR 0x27
// I2C 引脚定义(标准库,根据你的硬件修改)
#define I2C_PORT GPIOB
#define I2C_SCL_PIN GPIO_Pin_6
#define I2C_SDA_PIN GPIO_Pin_7
#define I2C I2C1
// 函数声明
void PCF8574_I2C_Init(void);
void PCF8574_WriteByte(uint8_t data);
void LCD1602_WriteCmd(uint8_t cmd);
void LCD1602_WriteData(uint8_t data);
void LCD1602_Init(void);
void LCD1602_ShowStr(uint8_t x, uint8_t y, char *str); //显示字符串
void LCD1602_ShowNum(uint8_t x, uint8_t y, int32_t num); // 显示整数
void LCD1602_ShowFloat(uint8_t x, uint8_t y, float num, uint8_t dot); // 显示浮点数
#endif
pcf8574_std.c
#include "pcf8574_std.h"
#include "SysTick.h"
// ########################### 关键修复:背光位固定为1 ###########################
#define LCD_BL 0x08 // 背光控制位(1=常亮,0=熄灭)
// I2C 初始化
void PCF8574_I2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// 复用开漏输出
GPIO_InitStruct.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_PORT, &GPIO_InitStruct);
I2C_InitStruct.I2C_ClockSpeed = 100000; // 100KHz 更稳定
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C, &I2C_InitStruct);
I2C_Cmd(I2C, ENABLE);
}
// PCF8574 写数据(自带背光)
static void PCF8574_Write(u8 data)
{
data |= LCD_BL; // 强制开启背光
while(I2C_GetFlagStatus(I2C, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C, ENABLE);
while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C, PCF8574_ADDR<<1, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C, data);
while(!I2C_CheckEvent(I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C, ENABLE);
delay_ms(1);
}
// LCD1602 写4位数据
static void LCD1602_Write4Bit(u8 data, u8 rs)
{
u8 temp = (data & 0xF0) | rs | LCD_BL;
PCF8574_Write(temp | 0x04); // EN=1
PCF8574_Write(temp & ~0x04);// EN=0
}
// 写命令
static void LCD1602_WriteCmd(u8 cmd)
{
LCD1602_Write4Bit(cmd, 0); // 高4位
LCD1602_Write4Bit(cmd<<4, 0); // 低4位
delay_ms(2);
}
// ########################### 关键修复:严格初始化时序 ###########################
void LCD1602_Init(void)
{
PCF8574_I2C_Init();
delay_ms(50); // 上电延时
// 4位模式初始化
LCD1602_Write4Bit(0x30, 0); delay_ms(5);
LCD1602_Write4Bit(0x30, 0); delay_ms(1);
LCD1602_Write4Bit(0x30, 0); delay_ms(1);
LCD1602_Write4Bit(0x20, 0); delay_ms(1);
LCD1602_WriteCmd(0x28); // 4位线,2行,5x8点阵
LCD1602_WriteCmd(0x0C); // 开显示,无光标(最常用)
LCD1602_WriteCmd(0x06); // 光标右移
LCD1602_WriteCmd(0x01); // 清屏
delay_ms(5);
}
// 显示字符串
/*
参数 名称 取值范围 通俗解释
x 列坐标 0 ~ 15 水平位置:0 = 最左边,15 = 最右边
y 行坐标 0 / 1 垂直位置:0 = 第一行,1 = 第二行
str 显示字符串 你要显示的文字 / 数字 / 符号
*/
void LCD1602_ShowStr_old(u8 x, u8 y, char *str)
{
u8 addr;
if(y == 0) addr = 0x80 + x;
else addr = 0xC0 + x;
LCD1602_WriteCmd(addr);
while(*str)
{
LCD1602_Write4Bit(*str, 1);
LCD1602_Write4Bit(*str<<4, 1);
str++;
}
}
// 功能:从x列开始显示字符串,自动清空 x~15列所有残留字符
// 比old好(见LCD1602_ShowNum里的说明,不清屏快速展示的内容会完全看不懂,这是严重问题),
// 但有个小问题,反复执行会一直闪
// 清屏是必须的,不知道为什么.
void LCD1602_ShowStr(uint8_t x, uint8_t y, char *str)
{
uint8_t addr;
uint8_t i;
uint8_t clear_len = 16 - x; // 清空:从x到行尾一共多少格
// 1. 计算光标位置
if(y == 0) addr = 0x80 + x;
else addr = 0xC0 + x;
LCD1602_WriteCmd(addr);
// 2. 直接清空 x~15列(底层写空格,无递归!)
for(i=0; i<clear_len; i++)
{
LCD1602_Write4Bit(' ', 1);
LCD1602_Write4Bit(' '<<4, 1);
}
// 3. 重新移动光标,显示字符串
if(y == 0) addr = 0x80 + x;
else addr = 0xC0 + x;
LCD1602_WriteCmd(addr);
while(*str)
{
LCD1602_Write4Bit(*str, 1);
LCD1602_Write4Bit(*str<<4, 1);
str++;
}
}
/**
* 功能:在指定位置显示 整数 (支持正负,如 -123、45678)
* x:列坐标(0~15)
* y:行坐标(0/1)
* num:要显示的整数 (int32_t 支持很大范围)
*/
void LCD1602_ShowNum(uint8_t x, uint8_t y, int32_t num)
{
char buf[16]; // 存储转换后的字符串
// 数字转字符串
sprintf(buf, "%d", num);
/*if(y == 0) LCD1602_ShowStr(0, 0, " ");
else LCD1602_ShowStr(0, 1, " "); 对于快速变化的内容,这两行是必须的,但为了通用性,放在了LCD1602_ShowStr里*/
// 调用原有字符串函数显示
LCD1602_ShowStr(x, y, buf);
}
/**
* 功能:在指定位置显示 浮点数 (支持正负,如 3.14、-2.5、100.00)
* x:列坐标(0~15)
* y:行坐标(0/1)
* num:浮点数
* dot:保留几位小数(推荐 1~2 位,屏幕足够显示)
*/
void LCD1602_ShowFloat(uint8_t x, uint8_t y, float num, uint8_t dot)
{
char buf[16];
// 根据小数位数格式化,自动转字符串
if(dot == 0) sprintf(buf, "%.0f", num); // 无小数
else if(dot == 1) sprintf(buf, "%.1f", num); // 1位小数
else if(dot == 2) sprintf(buf, "%.2f", num); // 2位小数
else sprintf(buf, "%.3f", num); // 3位小数
LCD1602_ShowStr(x, y, buf);
}
无线串口模块
又问了AI还有什么好东西, 另一个是无线串口模块, 长这样
好处, 无线串口不稀罕,无线下载器都又这个功能,但这个足够的小且是用蓝牙通信的,手机完全无缝使用.
先手机安装APP"SerialTest".这是接收蓝牙信号的app.
四根线,只需接三根即可:
VCC接3.3v
GND接GND
RXD接串口输出脚,如PA9
通电但蓝牙未连接时, 红灯闪烁.
此时打开手机蓝牙,找到"JDY-31-SPP"进行配对,输入1234.即可配对成功,此时红灯常亮. 只需要配对一次,以后都在APP"SerialTest"里连接
打开APP"SerialTest"
按如图1连接 按1,2,3
按如图2接收数据
点击"导出"默认把文件保存到下载文件夹
注意,无线串口工具断电之后再通电,需要手机在APP"SerialTest"的左下角点击重连一次(见图1的4). 红灯会从闪烁变为常亮
开发须知:串口必须使用9600波特率. 这是引入无线串口模块带来的唯一代码层侵入
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)