- 打卡等级:初来乍到
- 打卡总天数:6
- 最近打卡:2026-04-04 14:44:58
已绑定手机
新手上路
- 积分
- 49
|
今天是学习打卡的第二天,手上正好有一块LCD1602的屏,四针的,I2C接口,就尝试写了一个代码,显示字符,并打开背光灯。
#include "stc32g.h"
#include <intrins.h>
// I2C LCD1602地址(通常为0x27或0x3F)
#define LCD_ADDR 0x27
sbit P2_1 = P2^1;
sbit P2_0 = P2^0;
// I2C引脚定义
#define SDA_PIN P2_1
#define SCL_PIN P2_0
// LCD命令定义
#define LCD_CLEAR_DISPLAY 0x01
#define LCD_RETURN_HOME 0x02
#define LCD_ENTRY_MODE_SET 0x04
#define LCD_DISPLAY_CONTROL 0x08
#define LCD_CURSOR_SHIFT 0x10
#define LCD_FUNCTION_SET 0x20
#define LCD_SET_CGRAM_ADDR 0x40
#define LCD_SET_DDRAM_ADDR 0x80
// 延时函数
void delay_us(unsigned int us) {
while(us--) {
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++) {
for(j = 0; j < 1000; j++) {
_nop_();
}
}
}
// I2C起始信号
void I2C_Start() {
SDA_PIN = 1;
SCL_PIN = 1;
delay_us(5);
SDA_PIN = 0;
delay_us(5);
SCL_PIN = 0;
}
// I2C停止信号
void I2C_Stop() {
SDA_PIN = 0;
SCL_PIN = 1;
delay_us(5);
SDA_PIN = 1;
delay_us(5);
}
// I2C发送应答信号
void I2C_Ack() {
SDA_PIN = 0;
SCL_PIN = 1;
delay_us(5);
SCL_PIN = 0;
SDA_PIN = 1;
}
// I2C发送非应答信号
void I2C_NAck() {
SDA_PIN = 1;
SCL_PIN = 1;
delay_us(5);
SCL_PIN = 0;
SDA_PIN = 1;
}
// I2C检测应答信号
bit I2C_CheckAck() {
bit ack;
SDA_PIN = 1;
SCL_PIN = 1;
delay_us(5);
ack = SDA_PIN;
SCL_PIN = 0;
delay_us(5);
return ack;
}
// I2C发送一个字节
void I2C_SendByte(unsigned char dat) {
unsigned char i;
for(i = 0; i < 8; i++) {
SDA_PIN = (dat & 0x80) ? 1 : 0;
dat <<= 1;
SCL_PIN = 1;
delay_us(5);
SCL_PIN = 0;
delay_us(5);
}
I2C_CheckAck();
}
// I2C接收一个字节
unsigned char I2C_RecvByte() {
unsigned char i, dat = 0;
SDA_PIN = 1;
for(i = 0; i < 8; i++) {
SCL_PIN = 1;
delay_us(5);
dat <<= 1;
if(SDA_PIN) dat |= 0x01;
SCL_PIN = 0;
delay_us(5);
}
return dat;
}
// 向LCD发送命令或数据
void LCD_Send(unsigned char dta, bit rs) {
unsigned char high, low;
// 拆分4位数据
high = dta & 0xF0;
low = (dta << 4) & 0xF0;
I2C_Start();
I2C_SendByte(LCD_ADDR << 1);
// 发送高4位
I2C_SendByte(high | 0x04 | (rs ? 0x01 : 0x00)); // EN=1, RS=rs
I2C_SendByte(high | (rs ? 0x01 : 0x00)); // EN=0, RS=rs
// 发送低4位
I2C_SendByte(low | 0x04 | (rs ? 0x01 : 0x00)); // EN=1, RS=rs
I2C_SendByte(low | (rs ? 0x01 : 0x00)); // EN=0, RS=rs
I2C_Stop();
}
// LCD初始化
void LCD_Init() {
delay_ms(50); // 等待LCD上电稳定
// 初始化I2C引脚
P2M1 &= ~0x03; // P2.0(SCL), P2.1(SDA) 设为推挽输出
P2M0 |= 0x03;
// 4位模式初始化序列
LCD_Send(0x33, 0); // 8位模式
LCD_Send(0x32, 0); // 8位模式
LCD_Send(0x28, 0); // 4位模式,2行显示,5x8点阵
LCD_Send(LCD_DISPLAY_CONTROL | 0x04, 0); // 显示开,光标关
LCD_Send(LCD_CLEAR_DISPLAY, 0); // 清屏
LCD_Send(LCD_ENTRY_MODE_SET | 0x02, 0); // 增量模式,不移位
delay_ms(2);
}
// 在指定位置显示字符
void LCD_DisplayChar(unsigned char x, unsigned char y, unsigned char ch) {
unsigned char addr;
if(y == 0) addr = 0x80 + x;
else addr = 0xC0 + x;
LCD_Send(addr, 0); // 设置DDRAM地址
LCD_Send(ch, 1); // 写入数据
}
// 显示字符串
void LCD_DisplayString(unsigned char x, unsigned char y, unsigned char *str) {
unsigned char addr;
if(y == 0) addr = 0x80 + x;
else addr = 0xC0 + x;
LCD_Send(addr, 0); // 设置DDRAM地址
while(*str != '\0') {
LCD_Send(*str++, 1);
}
}
// 清屏
void LCD_Clear() {
LCD_Send(LCD_CLEAR_DISPLAY, 0);
delay_ms(2);
}
// 背光控制函数
void LCD_Backlight(bit state) {
I2C_Start(); // 起始信号
I2C_SendByte(LCD_ADDR << 1); // 发送设备地址
I2C_SendByte(state ? 0x08 : 0x00); // 控制背光
I2C_Stop(); // 停止信号
}
// 使用示例
// LCD_Backlight(1); // 打开背光
// LCD_Backlight(0); // 关闭背光
void main() {
LCD_Init();
LCD_DisplayString(0, 0, "Hello, World!");
LCD_DisplayString(0, 1, "STC32G12K128");
while(1) {
LCD_Backlight(1); // 可以添加其他功能
}
}
|
|