[PIC®/AVR®/dsPIC®产品] 程序出现异常

[复制链接]
1186|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 | 显示全部楼层

楼主程序可以公开吗?贴程序看下吧,这么说看不出什么原因
 楼主| 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;
        }            
    }   
}
 楼主| liliang9554 发表于 2023-3-31 22:13 | 显示全部楼层
但是一直跳不出while循环。
 楼主| 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;            
        }            
    }   
}
zhenykun 发表于 2023-3-31 22:13 | 显示全部楼层

还有什么现象?能再详细描述下吗?
 楼主| liliang9554 发表于 2023-3-31 22:15 | 显示全部楼层
甚至我还做了如下调试:根据第二种程序,别的什么都不该,就是把while语句的判断条件改成while(1),程序就不能正常执行。
 楼主| 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;
        }            
    }   
}
wyjie 发表于 2023-3-31 22:15 | 显示全部楼层
从逻辑上讲,如果busy = 0;能被执行,那么break肯定也能
happy_10 发表于 2023-3-31 22:20 | 显示全部楼层
break能执行又怎么会一直死在while语句里面不能出来呢?
 楼主| liliang9554 发表于 2023-3-31 22:21 | 显示全部楼层
我进行了单步调试,结果更加令我诧异:
采用第一种程序(即不用busy变量),temp读取的值最高位一直是1,通常是0x81;而改用第二种程序,temp就能读取到0x00。
 楼主| liliang9554 发表于 2023-3-31 22:21 | 显示全部楼层
但是我除了这个函数之后没有改变任何其他地方,为什么temp从PORTD口读到的值会不同呢?
 楼主| 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);
}
jlyuan 发表于 2023-3-31 22:23 | 显示全部楼层
时序没有问题?
hanwe 发表于 2023-3-31 22:25 | 显示全部楼层
硬件可能性大吗?
wenfen 发表于 2023-3-31 22:27 | 显示全部楼层
877A比较老了,如果可能的话,用新的料号使用MCC试一下
huangchui 发表于 2023-3-31 22:29 | 显示全部楼层
确实老了,只作学习之用。
 楼主| liliang9554 发表于 2023-3-31 22:31 | 显示全部楼层
关键在于,我看不出程序中的逻辑问题,我觉得以上三种程序应该都能运行才对啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

950

主题

11568

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部