搜索
bottom↓
回复: 4

AVR 1602LCD子程序请教!

[复制链接]

出0入0汤圆

发表于 2015-7-6 17:22:24 | 显示全部楼层 |阅读模式
本帖最后由 lxren 于 2015-7-6 17:43 编辑

大伙帮忙指点下这个1602的程序,基于IAR for AVR编译器,一直调不过。
有点怀疑读LCD1602忙状态的时候PORTA被编译器优化掉,是否要对PORTA加volatile做说明?要怎么加PORT的volatile???

程序如下:
/***************************************************************************************
****************************************************************************************
* FILE                : display.c
* Description        :
*                          
* Copyright (c) 2015 by Manden. All Rights Reserved.
*
* History:
* Version                Name                Date                                Description
*   0.1                ****                2015/06/18                Initial Version
   
****************************************************************************************
****************************************************************************************/


#include <iom16.h>
#include <string.h>
#include "HAL_Type.h"
#include "delay.h"
#include "display.h"


#define DataPort        PORTA
#define DataDDR        DDRA
#define CTRLPort        PORTB
#define CTRLDDR        DDRB

#define CLR_RS        PORTB_Bit0=0
#define SET_RS        PORTB_Bit0=1
#define CLR_RW        PORTB_Bit1=0
#define SET_RW        PORTB_Bit1=1
#define CLR_EN        PORTB_Bit2=0
#define SET_EN        PORTB_Bit2=1


void WaitForEnable(void)
{
        DataDDR &= 0x00;//数据口置为输入
        CLR_RS;
        SET_RW;
        SET_EN;
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        while((DataPort & 0x80)!=0)  //检测忙标志
                {
                CLR_EN;
                asm("nop");
                asm("nop");
                asm("nop");
                asm("nop");
                SET_EN;
                asm("nop");
                asm("nop");
                asm("nop");
                asm("nop");
                }
        CLR_EN;
        DataDDR |=0xff;
}

void write_cmd(unsigned char cmd)//写指令
{
       
        WaitForEnable();
        CLR_RS;
        CLR_RW;
        DataPort = cmd;
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        SET_EN;
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        CLR_EN;
}

void write_data(unsigned char da)//写数据
{
        WaitForEnable();
        SET_RS;
        CLR_RW;
        DataPort = da;
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        SET_EN;
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        CLR_EN;
}


void lcd_init()//LCD初始化
{
        DataPort &= 0x00;                //初始化0
        DataDDR |= 0xff;                //数据脚设置为输出
        CTRLPort &= 0xf8;                //控制信号设置为0
        CTRLDDR |=0x07;                //控制脚设置为输出
        write_cmd(0x38);        //设置8位格式,2行,5x7
        DelayMs(2);
        write_cmd(0x08);        //显示关闭
        DelayMs(2);
        write_cmd(0x06);        //设定输入方式,增量不移位
        DelayMs(2);
        write_cmd(0x01);        //清显示
        DelayMs(2);
        write_cmd(0x0c);        //整体显示,关光标,不闪烁
        DelayMs(2);
}


/********************************************************************
* 名称 : lcd1602_char(uchar row,uchar col,char sign)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
                 lcd1602_char(1,5,'b')
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void lcd1602_char(unsigned char row,unsigned char col,char sign)
{
        unsigned char a;
        if(row == 1) a = 0x80;
        if(row == 2) a = 0xc0;
        a = a + col - 1;
        write_cmd(a);
        write_data(sign);
}

/********************************************************************
* 名称 : lcd1602_string(uchar row,uchar col,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
                  lcd1602_string(1,5,"ab cd ef");
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void lcd1602_string(unsigned char row,unsigned char col,char *p)
{
        unsigned char a;
        if(row == 1) a = 0x80;
        if(row == 2) a = 0xc0;
        a = a + col - 1;
        write_cmd(a);
        while(1)
        {
                if(*p == '\0') break;
                write_data(*p);       
                p++;
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入10汤圆

发表于 2015-7-6 19:14:15 | 显示全部楼层
直接按照ic规格书指令表改为延时就好,不用查忙了

出0入0汤圆

 楼主| 发表于 2015-7-6 20:05:09 | 显示全部楼层
bias 发表于 2015-7-6 19:14
直接按照ic规格书指令表改为延时就好,不用查忙了

也试过了。。。
proteus仿真提示lcd busy,没显示。。。

出0入10汤圆

发表于 2015-7-6 22:05:12 | 显示全部楼层
lxren 发表于 2015-7-6 20:05
也试过了。。。
proteus仿真提示lcd busy,没显示。。。

仿真的不太清楚,实际我都用延时,大部分指令是36us左右,指令表有.

出0入0汤圆

 楼主| 发表于 2015-7-11 20:37:12 | 显示全部楼层
问题找到了。。。 while((DataPort & 0x80)!=0)  //检测忙标志————这一句是读取端口A的输入信号,要切到输入寄存器PINA,改成 while((PINA & 0x80)!=0)  //检测忙标志,就好了。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 01:33

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表