我正在学习嵌入式编程,并将LED板和按钮板连接到同一个PORT。
在chk_button函数下注释掉if语句,激活时某些按钮会将num预期增量+ 1加到num变量中.IE:按下按钮1将增加num。当前案例陈述适用于规范。
我理解案例陈述,当有效编译成查找表,因此占用空间更小,运行速度更快,但我不确定为什么我得到了我的错误。
我也对我的代码中的任何其他批评持开放态度。
// HARDWARE SETUP:
// PORTA is connected to the segments of the LED display. and to the pushbuttons.
// PORTA.0 corresponds to segment a, PORTA.1 corresponds to segement b, etc.
// PORTB bits 4-6 go to a,b,c inputs of the 74HC138.
// PORTB bit 7 goes to the PWM transistor base.
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 16000000
#define DIGIT_ONE 0x00
#define DIGIT_TWO 0x10
#define DIGIT_COLON 0x20
#define DIGIT_THREE 0x30
#define DIGIT_FOUR 0x40
//******************************************************************************
// debounce_switches
//Checks the state of the button number passed to it. It shifts in ones till
//the button is pushed. Function returns a 1 only once per debounced button
//push so a debounce and toggle function can be implemented at the same time.
//Adapted to check all buttons from Ganssel's "Guide to Debouncing"
//Expects active low pushbuttons on PINA port. Debounce time is determined by
//external loop delay times 12.
//Saves status of button (i) into a state array.
//******************************************************************************
int8_t debounce_switches(uint16_t *state, uint8_t i) {
state[i] = (state[i] << 1) | (! bit_is_clear(PINA, i)) | 0xE000;
if (state[i] == 0xF000) return 1;
return 0;
}
//******************************************************************************
// chk_buttons
//Checks the buttons. Calls debounce_switches in a loop passing both the state array
//and the current switch being checked.
//If debounce_switches returns a 1 for a switch, case statements determine which switch
//was activated, and increments count by the appropriate value.
//******************************************************************************
void chk_buttons(uint16_t *state, uint16_t *num)
{
uint8_t itr;
for( itr=0; itr<8; itr++)
{
if( debounce_switches(state, itr))
{
switch(itr)
{
case 0:
*num += 1;
break;
case 1:
*num += 2;
break;
case 2:
*num += 4;
break;
case 3:
*num += 8;
break;
case 4:
*num += 16;
break;
case 5:
*num += 32;
break;
case 6:
*num += 64;
break;
case 7:
*num +=128;
break;
}
/*
if (itr == 0) *num += 1;
else if(itr == 1) *num += 2;
else if(itr == 2) *num += 4;
else if(itr == 3) *num += 8;
else if(itr == 4) *num += 16;
else if(itr == 5) *num += 32;
else if(itr == 6) *num += 64;
else if(itr == 7) *num += 128;
*/
}
}
}
//******************************************************************************
// itoseven
// Accepts a number from 0 -9 Returns a hex value to display on the seven segment..
//******************************************************************************
uint8_t itoseven(uint8_t num)
{
uint8_t segnum;
switch(num)
{
case 0:
segnum = ~0x3F;
return segnum;
case 1:
segnum = ~0x06;
return segnum;
case 2:
segnum = ~0x5B;
return segnum;
case 3:
segnum = ~0x4F;
return segnum;
case 4:
segnum = ~0x66;
return segnum;
case 5:
segnum = ~0x6D;
return segnum;
case 6:
segnum = ~0x7D;
return segnum;
case 7:
segnum = ~0x07;
return segnum;
case 8:
segnum = ~0x7F;
return segnum;
case 9:
segnum = ~0x6F;
return segnum;
}
}
//***********************************************************************************
// segment_sum
//takes a 16-bit binary input value and displays the result to the LED board.
//***********************************************************************************
void segsum(uint16_t num) {
uint8_t ones;
uint8_t tens;
uint8_t hundreds;
uint8_t thousands;
//break up decimal sum into 4 digit-segments
ones = num % 10;
tens = (num/10)%10;
hundreds = (num/100)%10;
thousands = (num/1000)%10;
//determine how many digits there are
if(num < 10)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(num);
}
else if(num > 9 && num <100)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(ones);
_delay_ms(2);
PORTB = DIGIT_TWO;
PORTA = itoseven(tens);
}
else if(num > 99 && num < 1000)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(ones);
_delay_ms(2);
PORTB = DIGIT_TWO;
PORTA = itoseven(tens);
_delay_ms(2);
PORTB = DIGIT_THREE;
PORTA = itoseven(hundreds);
}
else if (num >999)
{
PORTB = DIGIT_ONE;
PORTA = itoseven(ones);
_delay_ms(2);
PORTB = DIGIT_TWO;
PORTA = itoseven(tens);
_delay_ms(2);
PORTB = DIGIT_THREE;
PORTA = itoseven(hundreds);
_delay_ms(2);
PORTB = DIGIT_FOUR;
PORTA = itoseven(thousands);
}
}
uint8_t main()
{
DDRB = 0xF0; //set port bits 4-7 B as outputs
uint16_t num = 0;
uint16_t state[8];
//initialize array values for debouncing
for(int i=0; i<8; i++)
{
state[i]= 0;
}
while(1)
{
//make PORTA an input port with pullups
DDRA = 0x00;
PORTA = 0xFF;
//enable tristate buffer for pushbutton switches
PORTB = 0x70;
//check the buttons. Increment by appropriate value if switch is active.
chk_buttons(&state, &num);
//rollover at 1023
if(num > 1023)
num = 1;
//switch PORTA to output
DDRA = 0xFF;
//Send num to display
segsum(num);
_delay_ms(2);
}
return 0;
}
答案 0 :(得分:1)
我已更新这些功能以删除开关,因为根本不需要它们。注意第一个使用算法代替开关,第二个使用一个易于在将来调整的表。此外,断言/错误检查您的输入,当事情横向发展时,您将成为一个更快乐的露营者。
void chk_buttons(uint16_t *state, uint16_t *num)
{
// Assert bad state and num here.
uint8_t itr;
for( itr=0; itr<8; itr++)
{
if( debounce_switches(state, itr))
{
*num += 1 << itr; // Could also use |= as that is what we are doing.
}
}
}
uint8_t itoseven(uint8_t num)
{
// assert num <= 9
const uint8_t kLookup[10] =
{~0x3f, ~0x06, ~0x5B, ~0x4F, ~0x66,
~0x6D, ~0x7D, ~0x07, ~0x7F, ~0x6F};
return kLookup[num];
}
对于最后一个功能,如果从4位数字开始检查并向后工作到单个数字,它将成为一个非常简单的循环来进行复杂的数字计算。只需将你的面具从10,000分为10.我会稍后发布该代码,因为我有时间。
更新
这是我编写的内容,用于演示这个想法。您需要为自己的功能修改它,因为它现在只输出ASCII。它不能用于负数(就像你的代码一样),但是如果检查/ ABS /前置一个减号字符就很容易添加。
int main(void)
{
int num = 9876;
// Starting at the 5th digit. You could use 1000 instead if
// there were only 4 digits or less ever.
int digitMask = 10000;
char output[16];
int index = 0;
// Handle 0 case.
if(num== 0)
{
output[index++] = '0';
}
else
{
// Skip leading 0's
while((num / digitMask) == 0)
{
digitMask /= 10;
}
// While there may be digits to process...
while(digitMask)
{
// Grab MS Digit and mod it away from total.
int digit = num / digitMask;
num %= digitMask;
// Convert to ASCII (you would use your own function)
output[index++] = digit + '0';
// Update mask - note we could use a for/loop here just as easily.
digitMask /= 10;
}
}
// Terminate string and print it.
output[index] = 0;
printf("%s", output);
return 0;
}