proteus8中用PIC16f877a8个独立按键解码led列源代码
时间: 2023-12-22 21:04:56 浏览: 77
下面是一个基于 PIC16F877A 的按键扫描和 LED 列控制的示例代码,使用 Proteus 8 进行仿真测试:
```
#include <xc.h>
// 定义按键和 LED 的引脚
#define KEY_PORT PORTB
#define KEY_TRIS TRISB
#define LED_PORT PORTD
#define LED_TRIS TRISD
// 定义按键状态和 LED 列状态数组
unsigned char keyState[4];
unsigned char ledState[8];
// 函数声明
void init();
unsigned char getKeyState(unsigned char row);
void setLedState(unsigned char column, unsigned char state);
void main(void) {
// 初始化
init();
while(1) {
// 按键扫描
for(unsigned char row = 0; row < 4; row++) {
unsigned char key = getKeyState(row);
if(keyState[row] != key) {
// 按键状态改变,更新状态数组
keyState[row] = key;
for(unsigned char column = 0; column < 8; column++) {
setLedState(column, (keyState[0] & (1 << column)) && (keyState[1] & (1 << column)) && (keyState[2] & (1 << column)) && (keyState[3] & (1 << column)));
}
}
}
}
return;
}
void init() {
// 设置输入输出引脚
KEY_TRIS = 0xF0;
LED_TRIS = 0x00;
// 初始化按键状态和 LED 列状态数组
for(unsigned char i = 0; i < 4; i++) {
keyState[i] = 0xFF;
}
for(unsigned char i = 0; i < 8; i++) {
ledState[i] = 0;
}
}
unsigned char getKeyState(unsigned char row) {
// 设置行低电平
KEY_PORT &= ~(1 << row);
// 延时一段时间,等待电平稳定
__delay_us(10);
// 读取列电平
unsigned char state = KEY_PORT >> 4;
// 恢复行高电平
KEY_PORT |= (1 << row);
return state;
}
void setLedState(unsigned char column, unsigned char state) {
if(ledState[column] != state) {
// LED 状态改变,更新状态数组和实际输出
ledState[column] = state;
if(state) {
LED_PORT |= (1 << column);
} else {
LED_PORT &= ~(1 << column);
}
}
}
```
说明:
- 本示例中使用了 4 行 8 列的矩阵按键和 LED 点阵,其中行和列分别通过 4 个输出引脚和 8 个输出引脚连接到 PIC16F877A 的端口 B 和端口 D 上。
- 函数 `getKeyState()` 用于扫描矩阵按键,返回当前列的状态,其中行的状态通过设置对应的输出引脚低电平实现,列的状态通过读取端口 B 上对应的 4 个输入引脚的电平实现。
- 函数 `setLedState()` 用于设置 LED 的状态,其中 LED 的状态通过设置对应的输出引脚高低电平实现,LED 列的状态保存在一个数组中,如果状态发生改变,就更新状态数组和实际输出。在本示例中,LED 列的状态是由按键状态决定的,只有当 4 个按键同时按下时,对应列的 LED 才会亮。
- 在 `main()` 函数中,循环扫描 4 行按键的状态,如果状态发生改变,就更新 LED 列的状态。注意,在更新 LED 列的状态时,要使用最新的按键状态数组,而不是在更新之前的状态数组。
阅读全文