书上原来是汇编程序,我给修改了用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;
}
//==============================================
============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)
{
unsigned char tmp1, tmp2;
//KEY_ROW =B'000111';KEY_COL=B'110000',假设按下按键为4,则低3位为101,高2位为10,按键码为101 101
//tmp2=key_read(KEY_ROW, KEY_COL); //扫描行
TRISA= TRISA | KEY_ROW;//TRISA= 111000 | 000111 = 111111 全输入,
PORTA= PORTA | KEY_COL;//PORTA= 000101 | 110000 = 110101 ,实际引脚000101,寄存器 110101
TRISA = TRISA & (~KEY_COL);//TRISA= 111101 & 001111=001101 ,PORTA=110101,引脚100101
temp2= PORTA & KEY_ROW;//temp2= 110101 & 000111=000101 就是按键码的低 3 位
//tmp1=key_read(KEY_COL, KEY_ROW); //扫描列
TRISA = TRISA | KEY_COL;//TRISA = 001101 | 110000 = 111101除按键按下行为输出,其余均为输入
PORTA = PORTA | KEY_ROW;//PORTA = 100101 | 000111 = 100101
TRISA = TRISA & (~KEY_ROW);//TRISA=111101 & 111000=111000
temp1 = PORTA & KEY_COL;//temp1 = 100101 & 110000=100000 就是按键码高2位
return tmp1 | tmp2; //返回按键码
}
这么理解是否正确?我再试验一下。
#include<pic.h>
__CONFIG(HS & PROTECT & PWRTEN & BOREN & WDTDIS);
//============全局变量====================
unsigned char KeyFlag=0x00;
unsigned char KeyHigh=0x00;
unsigned char KeyLow=0x00;
unsigned char KeyCode=0x00;
//===========函数声明======================
void KeyCheck(void);
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端口引脚状态变化中断
RBIF=0;
GIE=1;//开启总中断
while(1)
{
KeyCheck();//按键检测
}
}
//==============================================
void interrupt RbInt(void)
{
if(RBIE && RBIF)//判断中断使能和中断标志位
{
KeyFlag=0x01;
}
RBIF=0;//清零中断标志位,中断处理完毕再清除,好像就正常了
}
//==============================================
void KeyCheck(void)//按键检测函数
{
if(KeyFlag==0x01)
{
TRISB=TRISB | 0x0F;
PORTB=PORTB |0xF0;
TRISB=TRISB & 0x0F;
KeyLow=PORTB & 0x0F;
TRISB=TRISB | 0xF0;
PORTB=PORTB | 0x0F;
TRISB=TRISB & 0xF0;
KeyHigh=PORTA & 0xF0;
KeyCode = KeyLow | KeyHigh;
PORTD=KeyCode;
Delay();
KeyFlag=0x00;
}
else
{
KeyCode=0x00;
}
}
//==============================================
void Delay(void)//延时
{
int n;
for(n=0;n<=5000;n++)
continue;
}
//====================================================
我这样修改的,可是,按键了,没有反应啊!
一周热门 更多>