AVR单片机数码管显示拨码开关状态 - 解决数字只增不减问题

本文将介绍如何使用AVR单片机读取八位拨码开关的状态,并将其转换为十进制数,最终显示在数码管上。我们还会解决代码中数码管显示数字只能增大不能减小的问题,并提供完善后的代码和详细解释。

问题描述

在使用AVR单片机读取拨码开关并在数码管上显示其状态时,可能会遇到一个问题:数码管显示的数字只能随着拨码开关的拨动而增大,无法减小。

问题分析

出现这个问题的原因在于,在给数码管显示数字的函数displayDecimal()中,我们只是根据传入的十进制数来显示对应的数字,而没有实时地根据二进制数的变化来更新显示。换句话说,程序缺少一个机制来判断当前的二进制数是否发生了变化。

解决方案

为了解决这个问题,我们需要在主循环中添加一个变量来保存上一次读取的二进制数。每次读取拨码开关的状态后,都将当前读取的二进制数与上一次读取的二进制数进行比较。如果两者不相等,则说明二进制数发生了变化,需要更新上一次读取的二进制数,并调用displayDecimal()函数来显示新的十进制数。

完善后的代码

以下是经过修改后的完整代码:c#include <avr/io.h>#include <avr/delay.h>

#define F_CPU 8000000UL // 设置CPU时钟频率为8MHz

// 数码管显示的数字对应的编码const uint8_t segCode[10] = { 0b00111111, // 0 0b00000110, // 1 0b01011011, // 2 0b01001111, // 3 0b01100110, // 4 0b01101101, // 5 0b01111101, // 6 0b00000111, // 7 0b01111111, // 8 0b01101111 // 9};

// 读取八位拨码开关的状态uint8_t readSwitches() { return PINA;}

// 将二进制数转换为对应的十进制数uint8_t binaryToDecimal(uint8_t binary) { uint8_t decimal = 0; uint8_t weight = 1; while (binary > 0) { decimal += (binary & 0x01) * weight; binary >>= 1; weight *= 2; } return decimal;}

// 在数码管上显示十进制数void displayDecimal(uint8_t decimal) { uint8_t thousands = decimal / 1000; uint8_t hundreds = (decimal / 100) % 10; uint8_t tens = (decimal / 10) % 10; uint8_t units = decimal % 10;

PORTB = 0b00001111; // 全部数码管熄灭    PORTD = segCode[thousands]; // 在千位数码管上显示千位数字    PORTB = 0b00001110; // 打开千位数码管    _delay_ms(1);

PORTB = 0b00001111; // 全部数码管熄灭    PORTD = segCode[hundreds]; // 在百位数码管上显示百位数字    PORTB = 0b00001101; // 打开百位数码管    _delay_ms(1);

PORTB = 0b00001111; // 全部数码管熄灭    PORTD = segCode[tens]; // 在十位数码管上显示十位数字    PORTB = 0b00001011; // 打开十位数码管    _delay_ms(1);

PORTB = 0b00001111; // 全部数码管熄灭    PORTD = segCode[units]; // 在个位数码管上显示个位数字    PORTB = 0b00000111; // 打开个位数码管    _delay_ms(1);}

int main(void) { DDRA = 0x00; // 设置PA引脚为输入 DDRB = 0x0F; // 设置PB0~PB3引脚为输出 DDRD = 0xFF; // 设置PD0~PD7引脚为输出

PORTB = 0b00001111; // 全部数码管熄灭

uint8_t prevBinary = 0; // 上一次读取的二进制数

while (1) {        uint8_t switches = readSwitches(); // 读取拨码开关状态        uint8_t binary = switches; // 将拨码开关状态转换为二进制数

    if (binary != prevBinary) { // 如果当前二进制数与上一次不相等            uint8_t decimal = binaryToDecimal(binary); // 将二进制数转换为十进制数            displayDecimal(decimal); // 在数码管上显示十进制数            prevBinary = binary; // 更新上一次的二进制数        }    }

return 0;}

代码解释

  1. main()函数中,我们定义了一个名为prevBinary的变量,用于保存上一次读取的二进制数。2. 在主循环中,我们使用if (binary != prevBinary)语句来判断当前读取的二进制数是否与上一次读取的二进制数相等。3. 如果两者不相等,则说明二进制数发生了变化,需要更新prevBinary的值,并调用displayDecimal()函数来显示新的十进制数。

通过这种方式,我们就解决了数码管显示数字只能增大不能减小的问题,实现了根据二进制数的变化实时更新数码管显示的功能。

AVR单片机数码管显示拨码开关状态 - 解决数字只增不减问题

原文地址: https://www.cveoy.top/t/topic/fymy 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录