打印
[PIC®/AVR®/dsPIC®产品]

程序出现异常

[复制链接]
480|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
liliang9554|  楼主 | 2023-3-31 22:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
877A单片机用MPLAB X IDE写一个LCD12864的程序出现异常

使用特权

评论回复
沙发
jiajs| | 2023-3-31 22:08 | 只看该作者

楼主详细说说怎么回事啊,这么说太笼统了

使用特权

评论回复
板凳
liliang9554|  楼主 | 2023-3-31 22:10 | 只看该作者
单片机型号是PIC16F877A。
我在写一个LCD12864的程序,问题出在忙检测函数。并行数据的读写通过PORTD口。

使用特权

评论回复
地板
zhanghqi| | 2023-3-31 22:11 | 只看该作者

楼主程序可以公开吗?贴程序看下吧,这么说看不出什么原因

使用特权

评论回复
5
liliang9554|  楼主 | 2023-3-31 22:12 | 只看该作者
一开始我的程序是这样的:
void BusyCheck(void)
{
    unsigned char temp;
    TRISD = 0xFF;       //数据口设为输入
    RS = 0;
    RW = 1;
    while(1)
    {
        E = 1;
        temp = PORTD;   //读取DB7
        E = 0;
        if((temp & 0x80) == 0)
        {
            TRISD = 0x00;
            break;
        }            
    }   
}

使用特权

评论回复
6
liliang9554|  楼主 | 2023-3-31 22:13 | 只看该作者
但是一直跳不出while循环。

使用特权

评论回复
7
liliang9554|  楼主 | 2023-3-31 22:13 | 只看该作者

之后我添加了一个__bit类型的变量busy,就能正常运行了,函数改为如下
void BusyCheck(void)
{
    busy = 1;
    unsigned char temp;
    TRISD = 0xFF;       //数据口设为输入
    RS = 0;
    RW = 1;
    while(busy)
    {
        E = 1;
        temp = PORTD;   //读取DB7
        E = 0;
        if((temp & 0x80) == 0)
        {
            TRISD = 0x00;
            busy = 0;            
        }            
    }   
}

使用特权

评论回复
8
zhenykun| | 2023-3-31 22:13 | 只看该作者

还有什么现象?能再详细描述下吗?

使用特权

评论回复
9
liliang9554|  楼主 | 2023-3-31 22:15 | 只看该作者
甚至我还做了如下调试:根据第二种程序,别的什么都不该,就是把while语句的判断条件改成while(1),程序就不能正常执行。

使用特权

评论回复
10
liliang9554|  楼主 | 2023-3-31 22:15 | 只看该作者
void BusyCheck(void)
{
    busy = 1;
    unsigned char temp;
    TRISD = 0xFF;       //数据口设为输入
    RS = 0;
    RW = 1;
    while(1)//仅仅修改此处,把while(busy)改成while(1)
    {
        E = 1;
        temp = PORTD;   //读取DB7
        E = 0;
        if((temp & 0x80) == 0)
        {
            TRISD = 0x00;
            busy = 0;
            break;
        }            
    }   
}

使用特权

评论回复
11
wyjie| | 2023-3-31 22:15 | 只看该作者
从逻辑上讲,如果busy = 0;能被执行,那么break肯定也能

使用特权

评论回复
12
happy_10| | 2023-3-31 22:20 | 只看该作者
break能执行又怎么会一直死在while语句里面不能出来呢?

使用特权

评论回复
13
liliang9554|  楼主 | 2023-3-31 22:21 | 只看该作者
我进行了单步调试,结果更加令我诧异:
采用第一种程序(即不用busy变量),temp读取的值最高位一直是1,通常是0x81;而改用第二种程序,temp就能读取到0x00。

使用特权

评论回复
14
liliang9554|  楼主 | 2023-3-31 22:21 | 只看该作者
但是我除了这个函数之后没有改变任何其他地方,为什么temp从PORTD口读到的值会不同呢?

使用特权

评论回复
15
liliang9554|  楼主 | 2023-3-31 22:23 | 只看该作者
// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>

#define _XTAL_FREQ 4000000

__bit busy;
#define RS   RA5
#define RW   RA4
#define E    RA3
#define PSB  RA2
#define nRST RA1

void init(void);
void BusyCheck(void);
void WriteCmd(unsigned char cmd);
void WriteData(unsigned char dat);
void SetPos(unsigned char x, unsigned char y);
void Dis_Str(unsigned char *s);
void init_LCD(void);

void main(void)
{
    unsigned char sec = 0;
    init();
   
    init_LCD();
   
    SetPos(0,1);
    Dis_Str("第一行,第二格");
    SetPos(2,2);
    Dis_Str("time:");
    while(1)
    {
        SetPos(2,6);
        __delay_ms(1000);
        sec++;
        if(sec > 60)
            sec = 0;
        WriteData(sec / 10 + '0');
        WriteData(sec % 10 + '0');
    }
}

void init(void)
{
    PORTA = 0x02;
    TRISA = 0x00;
    ADCON1 = 0x06;
   
    PORTD = 0x00;
    TRISD = 0x00;
}

void BusyCheck(void)
{
    busy = 1;
    unsigned char temp;
    TRISD = 0xFF;       //数据口设为输入
    RS = 0;
    RW = 1;
    while(busy)
    {
        E = 1;
        temp = PORTD;   //读取DB7
        E = 0;
        if((temp & 0x80) == 0)
        {
            TRISD = 0x00;
            busy = 0;
            break;                   //照理说这里的brake语句可以跳出循环,但是不行,必须用busy变量的方法,原因不明。
        }            
    }   
}

void WriteCmd(unsigned char cmd)
{
    BusyCheck();
    RS = 0;
    RW = 0;
    E = 1;
    PORTD = cmd;
    E = 0;
}

void WriteData(unsigned char dat)
{
    BusyCheck();
    RS = 1;
    RW = 0;
    E = 1;
    PORTD = dat;
    E = 0;
}

void SetPos(unsigned char x, unsigned char y)
{
    unsigned char pos;
    switch(x)
    {
        case 0:x = 0x80;break;
        case 1:x = 0x90;break;
        case 2:x = 0x88;break;
        case 3:x = 0x98;break;
        default:break;
    }
    pos = x + y;
    WriteCmd(pos);
}

void Dis_Str(unsigned char *s)
{
    while(*s)
        WriteData(*s++);
}

void init_LCD(void)
{
    nRST = 1;   
    PSB = 1;   
    WriteCmd(0x30);
    WriteCmd(0x0C);
    WriteCmd(0x01);
    __delay_ms(1000);
}

使用特权

评论回复
16
jlyuan| | 2023-3-31 22:23 | 只看该作者
时序没有问题?

使用特权

评论回复
17
hanwe| | 2023-3-31 22:25 | 只看该作者
硬件可能性大吗?

使用特权

评论回复
18
wenfen| | 2023-3-31 22:27 | 只看该作者
877A比较老了,如果可能的话,用新的料号使用MCC试一下

使用特权

评论回复
19
huangchui| | 2023-3-31 22:29 | 只看该作者
确实老了,只作学习之用。

使用特权

评论回复
20
liliang9554|  楼主 | 2023-3-31 22:31 | 只看该作者
关键在于,我看不出程序中的逻辑问题,我觉得以上三种程序应该都能运行才对啊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

950

主题

11568

帖子

6

粉丝