求助看看我改的neutronlmk中子关于1602液晶的程序,有bug,不知道在哪里?
我把neutronlmk中子关于1602液晶的程序,中间一部分,表达的方式修改了,但是出现了问题。编译环境:ICCAVR6.31A
修改的地方:
直接进行位定义和位操作,让程序更加的直观易懂;
出现的bug:
isp下载编程,在下载成功的前提下,有时候能够显示,有时候不能显示;在偶尔能够显示的情况下,断电后再上电重开,又不显示了。
修改后的程序如下:
#include <iom16v.h>
#include <macros.h>
//数据线:PC0-PC7------>液晶D0-D7
//控制线:PD0-->RS;
// PD1-->R/W;
// PD2-->E;
// 定义一个寄存器(Register)或端口(Port)的八个位
typedef struct _bit_struct
{
unsignedbit0 : 1 ;
unsignedbit1 : 1 ;
unsignedbit2 : 1 ;
unsignedbit3 : 1 ;
unsignedbit4 : 1 ;
unsignedbit5 : 1 ;
unsignedbit7 : 1 ;
unsignedbit6 : 1 ;
}bit_field;
//定义一个宏,用来得到每一位的值,利用强制类型转换和指针
#define GET1_BITFIELD(PORTC) (*(volatilebit_field *)0x35)
#define GET2_BITFIELD(PORTD) (*(volatilebit_field *)0x32)
#define GET3_BITFIELD(DDRC) (*(volatilebit_field *)0x34)
#define GET4_BITFIELD(PIND) (*(volatilebit_field *)0x30)
//C语言关键字volatile确保本条指令不会因C编译器的优化而被省略.
//(bit_field *)(0x35)强制转换0x35为结构变量bit_field型的指针
//*,相当于引用这个地址上的内容
//定义寄存器或端口的地址(一般已经包含在头文件中了,本步可不做
//#define PORTc0x35
//定义每一个位
#define LCD_busy GET1_BITFIELD(PORTC).bit7
//忙信号
#define LCD_RSGET2_BITFIELD(PORTD).bit0
//数据、命令选择端,1-数据,0-指令
#define LCD_RWGET2_BITFIELD(PORTD).bit1
//读写选择端,1-读,0-写
#define LCD_ENGET2_BITFIELD(PORTD).bit2
//液晶使能
#define LCD_busy_ddrGET3_BITFIELD(DDRC).bit7
#define LCD_busy_pinGET4_BITFIELD(PINC).bit7
//检测忙信号
#define LCD_data_port PORTC
#define LCD_data_ddr DDRC
#define LCD_control_port PORTD
#define LCD_control_ddr DDRD
void delay_1ms(void );
void delay(unsigned int n) ;
void init_LCD_portCD(void);
void init_LCD(void);
void LCD_busy_en(void);
void LCD_write_order(unsigned char order,unsigned char lcd_busy_flag);
void LCD_write_data(unsigned char data);
void display_a_char(unsigned char position,unsigned char char_data);
void display_a_string(unsigned char col,unsigned char *ptr);
unsigned char str1[]=" stoner ";
unsigned char str2[]="buaamse ";
void main(void)
{
init_LCD_portCD();
init_LCD();
while(1)
{
display_a_string(0,str1);
display_a_string(1,str2);
}
}
void init_LCD_portCD(void)
{
LCD_data_port=0XFF;
LCD_data_ddr=0XFF;
LCD_control_port=0X07;
LCD_control_ddr=0X07;
}
void init_LCD(void)
{
//1-延时15ms
//2-写指令38H(不检测忙信号)
//3-延时5ms
//4-写指令38H(不检测忙信号)
//5-延时5ms
//6-写指令38H(不检测忙信号)
delay(15);
LCD_write_order(0x38,0);
delay(5);
LCD_write_order(0x38,0);
delay(5);
LCD_write_order(0x38,0);
// delay(5);
//7-(以后每次写指令、读写数据操作之前均需要检测忙信号)
//8-写指令38H:显示模式设置
//9-写指令08H:显示关闭
//10-写指令01H:显示清屏
//11-写指令06H:显示光标移动设置
//11-写指令0cH:显示开及光标设置
LCD_write_order(0x38,1);
LCD_write_order(0x08,1);
LCD_write_order(0x01,1);
LCD_write_order(0x06,1);
LCD_write_order(0x0c,1);
}
//正常读写操作之前必须检测LCD控制器状态
//检测忙信号、等待LCD空闲函数:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。
void LCD_busy_en(void)
{
LCD_busy_ddr=0;//设置PC口D7-busy口为输入
LCD_RS=0;
LCD_RW=1;
NOP();
LCD_EN=1;
while(LCD_busy_pin&LCD_busy);//等待D7-busy=0,表示准备好,若LCD_busy=1,则一直死循环等待变为0
LCD_EN=0;
LCD_busy_ddr=1;
}
//写指令函数: E=高脉冲 RS=0 RW=0 D0-D7=指令码
//order为指令,指定是否要检测LCD忙信号
void LCD_write_order(unsigned char order,unsigned char lcd_busy_flag)
{
if(lcd_busy_flag==1)LCD_busy_en();//若lcd_busy_flag为1,则要检测LCD忙信号,等待其空闲
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;//高脉冲
NOP();
LCD_EN=1;
LCD_data_port=order;
LCD_EN=0;
}
//写数据函数: E =高脉冲 RS=1 RW=0
void LCD_write_data(unsigned char data)
{
LCD_busy_en();
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;//高脉冲
NOP();
LCD_EN=1;
LCD_data_port=data;
LCD_EN=0;
}
//显示一个字符函数
//指定位置显示一个字符:第一行位置0~15,第二行16~31
//因为LCD第一行显示寄存器地址0X80-0X8F,第二行显示寄存器地址:0XC0-0XCF
//参数position指定位置0~31,char_data为要显示的字符
void display_a_char(unsigned char position,unsigned char char_data)
{
unsigned char position_tem;
if(position>=0x10)
position_tem=position+0xb0;
else
position_tem=position+0x80;
LCD_write_order(position_tem,1);
LCD_write_data(char_data);
}
//指定一行显示连续字符串:0显示在第一行,1显示在第二行,注字符串不能长于16个字符
//显示一行连续字符串函数
void display_a_string(unsigned char col,unsigned char *ptr)//参数col指定行,*ptr指字符串数组的首指针
{
unsigned char col_tem,i;
col_tem=col<<4;//若col为1(即在LCD第二行显示字符串),先把col左移4位,使显示字符的首位置改到第二行首位,即位置16
for(i=0;i<16;i++)
display_a_char(col_tem++,*(ptr+i));
}
/*************延时程序*******************/
void delay_1ms(void )//延时1ms
{
unsigned int i ;
for (i=0;i<600;i++);
}
void delay(unsigned int n)//延时nms
{
unsigned int i=0 ;
for(i=0;i<n;i++)
{
delay_1ms();
}
}
neutronlmk中子的源程序如下:
点击此处下载armok0148962.zip 先配置芯片的熔丝位,允许BOD监测,检测电压设置为4.0v试试。 “
先配置芯片的熔丝位,允许BOD监测,检测电压设置为4.0v试试”
马老师,试过之后还是不行,问题还在寻找过程中....痛苦ing.......... 你可以参考一下阿莫的范例
应该是初始化的问题
在范例里只要将初始化函数的0x28改成0x20循环3次就可以了 我原来也是怀疑,网站的范例有问题,看来也有人碰到了。
楼上的解决方法是对的。 不知道这样定义了位域有多大好处?
51扩展位操作,AVR不一定要。
#define LCD_RSGET2_BITFIELD(PORTD).bit0
#define LCD_RWGET2_BITFIELD(PORTD).bit1
LCD_RS=1;
LCD_RW=1;
未必就好用过下面的写法
#define LCD_RS0
#define LCD_RW1
PORTD|=(1<<LCD_RS);
PORTD|=(1<<LCD_RW);
PORTD|=(1<<LCD_RS)|(1<<LCD_RW);这样有优化能力
或写成宏指令
#define LCD_RS_0PORTD&=~(1<<0)
#define LCD_RS_1PORTD|= (1<<0)
#define LCD_RW_0PORTD&=~(1<<1)
#define LCD_RW_1PORTD|= (1<<1) 谢谢,三楼,我去试试,范例是有些问题的,刚下载可以,重新上电就乱码了 LCD_EN=0;//高脉冲
NOP();
LCD_EN=1;
LCD_data_port=data;
LCD_EN=0;
时序有问题
页:
[1]