PIC18F4520四位总线方式驱动LCD1602
求助:笔者参考PIC16f877四位总线方式驱动LCD1602的显示程序,编写了PIC18F4520四位总线方式驱动LCD1602的C程序,Proteus 8.6仿真不显示,用软件自带的库函数也没调出来,有2个周了,真的快把人逼疯了,不知该怎样调试,能否告知一下调试方法和C代码,,本人只会编译再看仿真,怎么找问题在哪呢,本人用PICC18编译器。 把你的代码传上来看看吧 //-----------------------------------------------------------------//名称: 1602液晶头文件LCD1602_4BIT.h
//-----------------------------------------------------------------
#ifndef _LCD1602_4BIT_H
#define _LCD1602_4BIT_H
#include <pic18.h> //可以省略
#define INT8U unsigned char
#define INT16Uunsigned int
//#define _XTAL_FREQ 32000000UL
//LCD命令
#define _LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_SETMODE 0x04
#define LCD_SETVISIBLE 0x08
#define LCD_SHIFT 0x10
#define LCD_SETFUNCTION 0x20
#define LCD_SETCGADDR 0x40
#define LCD_SETDDADDR 0x80
//=================
//LCD控制引脚
#defineRS LATBbits.LATB0
#defineRW LATBbits.LATB1
#defineE LATBbits.LATB2
//#defineRS PORTBbits.RB0 //PIC16单片机用法
//#defineRW PORTBbits.RB1
//#defineE PORTBbits.RB2
//LCD数据与方向端口定义
#define PORT_LCD_DAT PORTB //读引脚用PORTB,不用LATB
#define TRIS_LCD_DAT TRISB
#define LATB_LCD_CTL LATB //控制口
//#define TRIS_LCD_CTL TRISB //控制口方向寄存器
//-----------------------------------------------------------------
// 函数声明
//-----------------------------------------------------------------
void LCD_Initialize(void);
void LCD_BUSY_WAIT(void);
void ClearScreen(void);
void Write_LCD_Command (INT8U data);
void Write_LCD_Data(INT8U data);
void Set_LCD_POS(INT8U r, INT8U c);
void LCD_ShowString(INT8U r, INT8U c,char *str);
void LCD_ShowChar(INT8U r, INT8U c,char ch);
void delay(INT16U xms); //? ms MHZ
#endif
//#endif//多一个也没关系
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------
//名称: 1602液晶C文件LCD1602_4BIT.c
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//名称: 工作于四位模式的1602LCD显示程序参考pic16f877程序
//-----------------------------------------------------------------
#define_XTAL_FREQ32000000UL //32MHZ晶振
#include <pic18.h>
#define INT8U unsigned char
#define INT16Uunsigned int
#include "LCD1602_4BIT.h"
void delay(INT16U xms) ////延时283us@32MHZ
{
INT16U a,b;
for(a=xms;a>0;a--)
for(b=320;b>0;b--);
}
//-----------------------------------------------------------------
// 液晶初始化
//-----------------------------------------------------------------
void LCD_Initialize(void)
{
Write_LCD_Command(LCD_SETFUNCTION + 0x08); //0x28,4位模式,双行,5x7点阵
delay(15);
Write_LCD_Command(LCD_SETFUNCTION + 0x08); //4位模式,双行,5x7点阵
delay(15);
Write_LCD_Command(LCD_SETFUNCTION + 0x08); //4位模式,双行,5x7点阵
delay(15);
//以上3句属软件启动,后两句后加的,避免下载后不显示,须关闭电源重开机才显示正常
Write_LCD_Command(LCD_SETVISIBLE + 0x04); //0x0c,开显示光标,不闪烁
delay(15);
//Write_LCD_Command(LCD_SETMODE + 0x02); //模式设置0x06,自动递增
delay(15);
Write_LCD_Command(0x01); //清屏
delay(15);
Write_LCD_Command(0x0f);delay(15); //开显示,显示光标,光标闪烁
//Write_LCD_Command(0x06);delay(15); //光标右移
Write_LCD_Command(0x80);delay(15); //首行显示位置
}
//-----------------------------------------------------------------
// 清除屏幕
//-----------------------------------------------------------------
void ClearScreen(void)
{
Write_LCD_Command(_LCD_CLEAR); //清屏
Write_LCD_Command(LCD_SETDDADDR + 0x00); //光标归位
}
//-----------------------------------------------------------------
// 写LCD命令
//-----------------------------------------------------------------
void Write_LCD_Command(unsigned char cmd)
{
TRIS_LCD_DAT = 0x00; //输出口
//delay(5)接近1500us @32MHZ 共2个delay(5)改为__delay_ms(2)偏慢,调用库函数慢
//PORT_LCD_DAT = (cmd & 0xf0) | 0x04;delay(5);//仿真延时取消也可以
//PORT_LCD_DAT &= 0xfb; // E = 0;//取高4位数据成功
LATB = cmd & 0xf0;
RS = 0; RW = 0;E = 1;delay(5);E = 0;
//PORT_LCD_DAT = (cmd << 4) | 0x04;delay(5); //仿真延时取消也可以
LATB = cmd << 4;
//PORT_LCD_DAT &= 0xfb;//E = 0; //取低4位数据
RS = 0; RW = 0; E = 1;delay(5);E = 0;
LCD_BUSY_WAIT();
}
//-----------------------------------------------------------------
// 写LCD数据
//-----------------------------------------------------------------
void Write_LCD_Data(unsigned char dat)
{
LCD_BUSY_WAIT();
TRIS_LCD_DAT = 0x00; //输出口
//delay(5)接近1500us @32MHZ 共2个delay(5)改为__delay_ms(2)偏慢,调用库函数慢
//PORT_LCD_DAT = (dat & 0xf0) | 0x05; delay(5); //仿真延时取消也可以
//PORT_LCD_DAT &= 0xfb; //E = 0;
LATB = dat & 0xf0;
RS = 1; RW = 0; E = 1;delay(5);E = 0; //取高4位数据
//PORT_LCD_DAT = (dat << 4) | 0x05; delay(5); //仿真延时取消也可以
//PORT_LCD_DAT &= 0xfb; //E = 0; //取低4位数据
LATB = dat << 4;
RS = 1; RW = 0;E = 1;delay(5);E = 0;
}
//-----------------------------------------------------------------
// LCD忙等待
//-----------------------------------------------------------------
void LCD_BUSY_WAIT(void)
{
INT8U Hi,Lo;
TRIS_LCD_DAT = 0xf0; //高4位输入,低4位输出
//delay(5) delay(10)需2分12秒显示,单个字符定位准确,显示字符串完整 32MHZ
//delay(5)接近1500us @32MHZ 共4个delay(5)改为__delay_ms(2)
//用__delay_ms(2)仿真用4分钟显示字符
do{
//PORT_LCD_DAT = 0x00; //端口写0
LATB=0x00; //寄存器写0
RW = 1;RS = 0;
E = 1;delay(5);Hi = PORT_LCD_DAT;delay(5);E = 0; //这里不能加延时
E = 1;delay(5);Lo = PORT_LCD_DAT;delay(5);E = 0;
//PORT_LCD_DAT = 0x06;__delay_ms(2);Hi = PORT_LCD_DAT;__delay_ms(2);E = 0;
//PORT_LCD_DAT |= 0x04;__delay_ms(2);Lo = PORT_LCD_DAT;__delay_ms(2);E = 0;
}while(Hi & 0x80);
}
//-----------------------------------------------------------------
// 设置显示位置(行,列)
//-----------------------------------------------------------------
void Set_LCD_POS(INT8U r, INT8U c)
{
//
if(r == 0) Write_LCD_Command(0x80 | c);
else if(r == 1) Write_LCD_Command(0xc0 | c);
}
//-----------------------------------------------------------------
// 显示字符串(行,列,字符串)
//-----------------------------------------------------------------
void LCD_ShowString(INT8U r, INT8U c,char *str)
{
INT8U i;
Set_LCD_POS(r,c);
//
for(i = 0; i < 16 && str != '\0';i++)
{ Write_LCD_Data(str); }
//
//while(i < 16)
//{Write_LCD_Data(' ');i++; }
}
//-----------------------------------------------------------------
// 显示字符(行,列,字符)
//-----------------------------------------------------------------
void LCD_ShowChar(INT8U r, INT8U c,char ch)
{
Set_LCD_POS(r,c);
Write_LCD_Data(ch);
}
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
//PIC18F4520单片机
// MPLAB IDE V8.60picc18编译器,支持picc16f的编译器
#include <pic18.h>
//#include <delays.h>
//#include <stdio.h>
//#include <XLCD.h>
//__PROG_CONFIG(1,0xc800); //
//默认0x0700, 0xc800使能振荡器切换,使能故障保护时钟监视,内部振荡RA6/7作端口引脚
//__PROG_CONFIG(1,0xc100); //PIC的配置字1,使能振荡器切换,使能故障保护时钟监视,XT振荡模式
//__PROG_CONFIG(1,0x4800); //不使能振荡器切换,使能故障保护时钟监视,内部振荡RA6/7作端口引脚
//__PROG_CONFIG(1,0xc200); //PIC的配置字1 0xc200外部HS振荡
__PROG_CONFIG(2,0x0A16); //PIC的配置字2
__PROG_CONFIG(3,0x8100); //PIC的配置字3
__PROG_CONFIG(4,0x0081); //PIC的配置字4
__PROG_CONFIG(5,0xC00F); //PIC的配置字5
__PROG_CONFIG(6,0xE00F); //PIC的配置字6
__PROG_CONFIG(7,0x400F); //PIC的配置字7
#include "LCD1602_4BIT.h"
#define_XTAL_FREQ32000000UL //8MHZ晶振
//32MHZ时钟可以采用最大的延时库函数 __delay_ms(20);
#define INT8U unsigned char
#define INT16Uunsigned int
//PIC18F4520系统时钟源初始化
void PIC18_OSC_Init(void)
{
OSCCON = 0x70; //PIC18F4520的OSCCONbits.IRCF2:0=111内部RC时钟源8MHZ
OSCTUNEbits.PLLEN = 1; //使能内部4倍PLL功能32MHZ
}
void main(void)
{
CMCON = 0x07; // Disable comparators
ADCON1 = 0x0F; // Disable Analog functions
TRISA = 0x00;
//PIC18_OSC_Init( ); // MHZ
delay(2000);
LCD_Initialize(); // Initialize LCD
delay(2000);
//检测液晶屏显示情况
LCD_ShowChar(0,15,'H'); //第0行1列显示字符'H'(行,列,字符)
//LCD_ShowChar(1,0,'A'); //第0行1列显示字符'A'(行,列,字符)
delay(2000);delay(20);delay(20);
LCD_ShowString(0,3,"Testing TC74"); //第0行0列显示(行,列,字符串)
// LCD_ShowString(1,1,"Thermal sensor"); //第1行0列显示
//__delay_ms(20);__delay_ms(20);__delay_ms(20);__delay_ms(20);
delay(1); //延时283us@32MHZ
//Write_LCD_Command(_LCD_CLEAR); // CLEAR display
PORTA = 0xff; delay(2000);
PORTA = 0x00; delay(2000);
while(1);
}
pic16f877仿真通过
RB4~RB7接液晶屏的D4~D7 是不是液晶屏供电有问题? 现在是Proteus仿真没通过,下载也没通过
先编一段程序,测试 RS、RW、E、data 等内容,确保每个管脚的操作都是正确的。
比如:单步运行 RS = 0,用万用表或者示波器实测 RS 信号是不是零;然后 RS = 1,实测输出对不对。
确保每个信号的操作都正确,剩下就是照搬例程了。
你可以尝试禁用编译器的优化设置,来查看是否有不同的结果。 LCD的初始化是驱动LCD的关键,确保初始化的时序和延时正确。 仿真中可能存在时序问题,特别是在写命令和数据时的时延。如果没有足够的延时,LCD可能没时间更新数据。 检查Proteus中LCD元件的配置。特别是LCD的Vcc和GND是否连接正确,控制端口是否正确设置。
页:
[1]