跳到主要内容

与 PIC 单片机接口的 16×2 LCD

在本节中,我们将学习如何将 16×2 LCDPIC18F4550 微控制器(属于 PIC18F 系列)进行接口连接。

1. PIC18F4550 的特性

  • PIC18F4550 属于 PIC18F 系列;它是一个 8 位微控制器,采用 RISC 架构。PIC18F4550 在 PDIP(双列直插封装)封装下具有 40 引脚,TQFP(四方扁平封装)封装下为 44 引脚。

  • 内置 32 KB 闪存、2048 字节 SRAM(同步随机存取存储器)和 256 字节 EEPROM(电可擦可编程只读存储器)。

  • 提供 35 个 I/O 引脚用于与其他外设接口与通信;包括 13 通道的 10 位模数转换器(用于接口与通信模拟外设,如直流电机、光敏电阻等)。

  • 拥有 2 个 CCP 和 1 个 ECCP 模块(增强捕获/比较模块),主要用于调制与波形生成。CCP 模块是 16 位寄存器,用作捕获、比较、PWM 及占空比寄存器。

  • 配有 SPI(串行外围接口)和 I²C(集成电路间互连)模块,支持主/从模式。具有 USB 流式并行端口(SPP)。

  • 内置 4 个定时器模块(timer0 到 timer3)、2 个比较器模块和 3 个外部中断。双振荡器选项允许微控制器与 USB 模块运行于不同时钟速率。工作电压范围为 2.0V 至 5.5V。

2. 16×2 LCD 与 PIC 单片机接口电路图

alt text

3. 16×2 LCD 接 PIC 的电路说明

电阻 R1 用于调节 LCD 的对比度。晶振(12 MHz)连接至 PIC18F4550 的 OSC1 与 OSC2 引脚,作为系统时钟。电容 C2 和 C3 起滤波作用,用于晶振。使用不同端口或引脚连接 LCD 前,请查阅数据手册确认这些引脚是通用 I/O 还是特殊功能引脚。

4. 编程 PIC 以接口 16×2 LCD

与 8051 接口 LCD 的方式类似,基础概念与编程思路几乎相同。

在 PIC 的 LCD 初始化中:写入数据时,R/W 引脚应拉低,Enable 引脚应拉高;写命令时,RS 应拉低,R/W 应拉低,Enable 应拉高。

4.1. 初始化 LCD 功能

lcdcmd(0x38); // 配置 LCD 为 8 位模式、2 行、5×7 点阵  
lcdcmd(0x0C); // 显示开,光标关
lcdcmd(0x01); // 清屏
lcdcmd(0x06); // 光标自增
lcdcmd(0x80); // 设置光标位置为第 1 行第 1 列

4.2. 向 LCD 发送命令

  • rs = 0;寄存器选择引脚拉低。
  • rw = 0;读/写引脚拉低,表示写入命令至 LCD。
  • en = 1;使能引脚拉高。

4.3. 向 LCD 发送数据

  • rs = 1;寄存器选择拉高,选择数据寄存器。
  • rw = 0;读/写引脚拉低,表示写操作。
  • en = 1;使能引脚拉高。

5. 编程步骤

  • 在系统中安装 MPLAB,创建新项目,选择 PIC18F 系列,并添加 PIC18F4550 控制器。
  • 选择已安装的编译器并添加源文件。粘贴下列代码后运行,程序已预编译且测试通过,无错误。

6. 与 PIC18F4550 接口 LCD 的程序

#define rs LATA.F0  
#define rw LATA.F1
#define en LATA.F2
#define lcdport LATB

void lcd_init();
void lcdcmd(unsigned char);
void lcddata(unsigned char);
unsigned char data[20] = "hello world";
unsigned int i = 0;

void main(void)
{
TRISA = 0; // 配置 Port A 为输出端口
LATA = 0;
TRISB = 0; // 配置 Port B 为输出端口
LATB = 0;
lcd_init(); // LCD 初始化
while (data[i] != '\0')
{
lcddata(data[i]); // 调用 lcddata 将字符逐个发送
i++;
Delay_ms(300);
}
}

void lcd_init()
{
lcdcmd(0x38);
lcdcmd(0x0C);
lcdcmd(0x01);
lcdcmd(0x06);
lcdcmd(0x80);
}

void lcdcmd(unsigned char cmdout)
{
lcdport = cmdout;
rs = 0;
rw = 0;
en = 1;
Delay_ms(10);
en = 0;
}

void lcddata(unsigned char dataout)
{
lcdport = dataout;
rs = 1;
rw = 0;
en = 1;
Delay_ms(10);
en = 0;
}