张明峰的《PIC单片机入门与实战》第五章,PORTB改写为C程序,与汇编仿真结果不一致,帮忙

2020-02-09 11:36发布

书上原来是汇编程序,我给修改了用PORTD输出扫描到的按键码,可以正常的显示,按下某个按键,就会显示出某个按键码,延时结束后,LED就会灭掉。而修改成C程序,按下某个按键,可以正常显示按键码,但是延时结束后,仍然显示,直到按新的按键,才会发生变化。可以帮忙修改一下么?谢谢了!
另外,新手,尽量讲的详细一些,谢谢!

Proteus仿真电路以及汇编、C程序ourdev_556000.rar(文件大小:19K) (原文件名:按键中断仿真.rar)

Proteus仿真图片 (原文件名:仿真.jpg)

C源程序,这些都包含在附件中,这个是给不想下附件的看的。
//=============头文件及配置===================
#include<pic.h>
__CONFIG(HS & PROTECT & PWRTEN & BOREN & WDTDIS);
//============全局变量====================
unsigned char KeyCode[8];
unsigned char KeySaved=0x00;
unsigned char KeyCurrent=0x00;
//===========函数声明======================
void KeyCheck(unsigned char KeySaved,unsigned char KeyCurrent);
void Delay(void);
//===========主函数========================
main()
{
        TRISB=0xF0;//PORTB高4位输入,低4位输出
        TRISD=0x00;//PORTD全输出
        PORTD=0x00;//PORTD清零
        PORTB=0x00;//PORTB清零,PORTB=B'11110000'
        RBPU=0;//在C里,NOT_RBPU位即RBPU位,开启PORTB的内部弱上拉
        RBIE=1;//开启PORTB端口引脚状态变化中断
        GIE=1;//开启总中断
        while(1)
        {
                PORTD=0x00;
                PORTB=0x00;
                KeyCheck(KeySaved,KeyCurrent);//按键检测
        }               
}
//==============================================
void interrupt RbInt(void)
{
    unsigned char ScanCode=0xEF;//定义按键扫描
    unsigned int k;
     if(RBIE && RBIF)//判断中断使能和中断标志位
     {
         RBIF=0;//清零中断标志位
         if((PORTB & 0xF0)!=0xF0)//如果有按键按下
            {
                 for(k=0;k<5;k++)
                    {
                       PORTB=ScanCode;//输出初始扫描值,PORTB的引脚上逻辑电平高4为不变
                       if((PORTB & 0xF0)!=0xF0)
                       {
                           KeyCode[KeyCurrent]=PORTB;
                           break;
                          }
                      else
                        {
                           ScanCode=ScanCode>>1;//扫描码循环右移,这个移的乱七八糟的
                                               //不知道是仿真的问题,还是移位的问题
                                              //原理就是低4为依次循环输出0,而其他位为高
                            }
                    }                       
               }
              KeyCurrent++;//当前按键存储偏移位置加1
               KeyCurrent=KeyCurrent & 0x07;//确保按键存储偏移位置小于8
        }
}
//==============================================
void KeyCheck(unsigned char KeySaved,unsigned char KeyCurrent)//按键检测函数
{
       if(KeyCurrent!=KeySaved)//如果当前按键偏移位置和已有的按键偏移位置不相等,则有新的按键
          {
              PORTD=KeyCode[KeySaved];//读保存的按键码
              Delay();//延时显示
              KeySaved = KeyCurrent;//已有按键偏移位置加1,与当前按键偏移位置同步
              //KeySaved = KeySaved & 0x07;//确保按键已存储偏移位置小于8
          }
          else PORTD=0x00;
}
//==============================================
void  Delay(void)//延时
{
   int n;
   for(n=0;n<=5000;n++)
   continue;
}
//==============================================
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
17条回答
millwood0
2020-02-11 02:56
this hopefully will get you on the right track.

============code===============
#include <htc.h>
#include <string.h>
#include "lcd_3wi.h"
#include "delay.h"

__CONFIG(MCLRDIS & WDTDIS & BORDIS & PWRTEN & INTIO);

#define LOOP_PIN                        (1<<5)                                //led indicator, on portC
#define KEY_PORT                        PORTA                                //leds on porta. needs to be able to cover the keypad.
#define KEY_DIR                                TRISA
#define KEY_SET(bits)                KEY_PORT |= (bits)        //set bits
#define KEY_CLR(bits)                KEY_PORT &=~(bits)        //clear bits
#define KEY_FLP(bits)                KEY_PORT ^= (bits)        //flip bits
#define KEY_IN(bits)                KEY_DIR |= (bits)                //bits as input
#define KEY_OUT(bits)                KEY_DIR &=~(bits)                //bits as output
#define KEY_COL                                0b110000                        //column connection bits
#define KEY_ROW                                0b000111                        //row connection bits
#define sleep()                                asm("sleep")                //sleep macro

unsigned char vRAM[17];                                //lcd buffer
const unsigned char str0[]="16F684 KeyScan 2";
const unsigned char str1[]="k=           ";

void mcu_init(void ) {                                //reset the mcu
        ANSEL=0x00;                                                //all pins gpio
        CMCON0=0x07;                                        //analog comparators off
        IRCF2=1, IRCF1=1, IRCF0=0;                //running at 4mhz
        LCD_DIR &=~LOOP_PIN;                                //LOOP_PIN as output
        LCD_CLR(LOOP_PIN);                                //clear loop_pin
}

void uctoa(char *s, unsigned char ul, unsigned char length) {        //convert unsigned long to a string, 3 dps
        unsigned char i;
       
        i=length;
        do {
//                if (i==(length-3)) s[i--]='.';
                s[i--]=ul % 10 + '0';
                ul = ul / 10;
        } while (ul);
}

unsigned char key_read(unsigned char in_bits, unsigned char out_bits) {                //output on out_bits and read in_bits
        KEY_IN(in_bits);                                                                //set in_bits to be input
        KEY_SET(out_bits); KEY_OUT(out_bits);                         //output 1 on out_bits
        return KEY_PORT & in_bits;
}

unsigned char key_detect(void) {                                        //return the cycle count
        unsigned char tmp1, tmp2;
        tmp2=key_read(KEY_ROW, KEY_COL);                                //read horizontal scan
        tmp1=key_read(KEY_COL, KEY_ROW);                                //read vertical scan
        return tmp1 | tmp2;
}

void
main(void)
{        unsigned char t1;
        unsigned char i=0;

        mcu_init();                                                        //initialize the mcu
        lcd_init();                                                        //initialize the lcd
        strcpy(vRAM, str0); lcd_display(LCD_Line0, vRAM);
        while (1){
                KEY_DIR &=~KEY_ROW;                                //row as output
                KEY_PORT |=KEY_ROW;                                //set key_row
                if (KEY_PORT & KEY_COL) {                        //see if a key is pressed
                        t1=key_detect();                        //read the kaypad
                        strcpy(vRAM, str1);
                        uctoa(&vRAM[2], i++, 4);
                        uctoa(&vRAM[8], t1, 4);
                        lcd_display(LCD_Line1, vRAM);
        //                LED_EMIT(LED_A, LED_K); delay_us(t1>>4);
        //                simple_pwm(t1>>4, LED_A, LED_K);
                }
                LCD_FLP(LOOP_PIN);
                //do something else
                //delay_ms(100);
                //TODO Auto-generated main function
        }
}
============end of code=================

the code energies KEY_ROW, and then reads back KEY_COL to see if a key is pressed.

if a key is pressed, it goes into key_detect() to see which key is pressed and displays it on the lcd.


here is the sim.


(原文件名:16F684 keypad detect 3.PNG)

一周热门 更多>