lcd1602

看一个项目里有PCF8574 和 HD44780,我好奇,板子上又没有,这是干嘛的, 问AI,是一种lcd1602模块,长这个样子
在这里插入图片描述
好处, 只需要四根线就可以让任何板子有个小显示屏.
使用IIC通信, 固定使用PB6,PB7两个引脚 (我的板子), 街上这两个,和3.3v和gnd就可以工作了.
引入步骤 keil:

  1. copy2个文件到 E:\keil_v5_git_workspace\lcd1602_test\App\lcd
  2. 在keil里add这2个文件 ‘pcf8574_std.c’,‘pcf8574_std.h’
  3. keil里魔法棒 include path加 lcd
  4. main.c里加#include “pcf8574_std.h”
  5. stdPeriph-driver里引入 stm32f10x_i2c.c
  6. 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波特率. 这是引入无线串口模块带来的唯一代码层侵入

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐