十进制转BCD
Converting decimal to BCD
我目前正在做一项作业,该作业使用微控制器和电路通过 LED 显示二进制小数。我必须使用三个按钮:一个增加,一个减少,最后一个重置。我的接线和配置已经完成。另一方面,我的代码有一些小故障,我无法仅通过 C class 的介绍来修复这些小故障。我正在使用代码编写器。第一个问题:我在 "Tens" 部分 (MSB) 上的计数器并没有停在 9,而是开始显示二进制 10-15。前四位是个位(右),后四位是十位(左)例如:1010 0001
但最大值是 1001 1001
。第二个问题:如果我递减该值,则从零开始,计数器显示 95 而不是 99。
例如:从 0000 0000
开始递减显示 1001 0101
。我尝试使用 if 语句为 MSB 设置一个条件,如果大于 10,则停止,但代码没有 运行。我对代码所做的几乎所有修改都会阻止它正常工作。
#include <msp430.h>
unsigned int dec2bcd(unsigned int num);
void delay(void);
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR = 0xFF;
P2DIR = 0xF0;
unsigned int c;
unsigned int count = 0x00;
while(1){
if((P2IN & BIT0) == BIT0){
count++;
c = dec2bcd(count);
}
else if((P2IN&BIT1) == BIT1){
count--;
c = dec2bcd(count);
}
else if((P2IN&BIT2) == BIT2){
count = 0x00;
c = dec2bcd(count);
}
delay();
P1OUT = c;
}
}
unsigned int dec2bcd(unsigned int num)
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10;
temp = num/10;
tens = temp<<4;
return (tens + ones);
}
void delay(void)
{
volatile unsigned int i, j;
for(i=10000; i>0; i--)
{
for(j=3; j>0; j--){
}
}
}
使用这个有什么限制吗:
if((P2IN & BIT0) == BIT0){
count++;
if (count == 100)
count = 0;
c = dec2bcd(count);
}
else if((P2IN&BIT1) == BIT1){
if (count == 0)
count = 100;
count--;
c = dec2bcd(count);
}
让我们在 countBDC 中计数。
unsigned countBCD = 0;
unsigned count = 0;
while(1){
if((P2IN & BIT0) == BIT0){
count++;
countBCD++;
if ((countBCD & 0xF) >= 0xA) {
// of course can combine these 2 lines
countBCD -= 0xA;
countBCD += 0x10;
if ((countBCD & 0xF0) >= 0xA0) {
countBCD -= 0xA0;
countBCD += 0x100;
...
// similar code for decrement
或者使用BCD增量函数
unsigned BCD_inc(unsigned x) {
unsigned carry = 1;
unsigned mask10 = 10;
unsigned maskNibble = 15;
while (carry) {
x += carry;
if ((x & maskNibble) >= mask10) {
x -= mask10;
mask10 <<= 4;
maskNibble <<= 4;
carry <<= 4;
} else {
carry = 0;
}
}
return x;
}
我现在手边没有 LED 条,但这显示了如何在小数范围内工作,但仅在输出点进行转换。实际值保持在 0..99
范围内(注意当我递减时模数是如何完成的)。然后将值拆分为 BCD 半字节,并将它们组合起来输出。
#include <stdio.h>
void display(int num, char *msg)
{
int lsnib = num % 10; // decimal value of each nibble
int msnib = num / 10;
int ledpatt = (msnib << 4) + lsnib; // recombine as BCD
printf("%02X Expected %s\n", ledpatt, msg);
}
int main(void){
int value;
value = 42;
display (value, "forty two"); // display 42
value = 0;
display (value, "zero"); // display 0
value = 99;
display (value, "ninety nine"); // display 99
value = (value + 1) % 100; // increment from 99
display (value, "zero"); // should display 0
value = (value -1 + 100) % 100; // decrement from 0
display (value, "ninety nine"); // should display 99
return 0;
}
程序输出
42 Expected forty two
00 Expected zero
99 Expected ninety nine
00 Expected zero
99 Expected ninety nine
为什么看到95?
如@Olaf所述,msp430使用16位整数。
当您执行 count = 0u -1
时,计数会自动换行到 65535
;
unsigned int dec2bcd(unsigned int num) // num is now 65535
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10; // 65535%10 = 5
temp = num/10; // 65535/10 = 6553
tens = temp<<4; // what's displayed is by tens is actually the lower
// 4 bits of tens, so tens is 6553%16=9
return (tens + ones);// so the result is 95
}
为什么十可以超过10
同样的问题,因为你的输入大于99。
unsigned int dec2bcd(unsigned int num) // say num is now 100
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10; // 100%10 = 0
temp = num/10; // 100/10 = 10, or 0x0A
tens = temp<<4;
return (tens + ones);// so the result is A0
}
你应该做什么?
在您的代码中,将范围限制为 0-99,您可以选择环绕 (99+1=0, and 0-1=99) 或饱和 (99+1=99, 0) -1=0)。不过你需要什么,你自己写吧:C语言没有提供。
这是解决了我之前遇到的问题的新代码。它可能不是最佳的,但我设法让它发挥作用。我添加了两个创建环绕的 if 语句,并通过实施模数修改了 dec2bcd 转换器。 "tens" 部分中的模数有助于解决显示问题。
谢谢你们帮助我!现在我明白了我的语法错误,感谢你向我展示了我需要关注的范围更广。祝我好运,我希望我能得到额外的荣誉。下次见。
#include <msp430g2553.h>
unsigned int dec2bcd(unsigned int num);
void delay(void);
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR = 0xFF;
P2DIR = 0x00;
unsigned int c;
unsigned int count = 0x00;
//Here are some modified portions to create wrap around
while(1){
if((P2IN & BIT0) == BIT0){
count++;
if(count == (99+1)){
count = 0x00;
}
c = dec2bcd(count);
}
else if((P2IN&BIT1) == BIT1){
count--;
if(count == (0-1)){
count = 0x63;
}
c = dec2bcd(count);
}
else if((P2IN&BIT2) == BIT2){
count = 0x00;
c = dec2bcd(count);
}
delay();
P1OUT = c;
}
}
unsigned int dec2bcd(unsigned int num)
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10;
temp = num/10;
//I used modulus here to get rid of the improper display issue
tens = (temp%10)<<4;
return (tens + ones);
}
void delay(void)
{
volatile unsigned int i, j;
for(i=10000; i>0; i--)
{
for(j=3; j>0; j--){
}
}
}
我目前正在做一项作业,该作业使用微控制器和电路通过 LED 显示二进制小数。我必须使用三个按钮:一个增加,一个减少,最后一个重置。我的接线和配置已经完成。另一方面,我的代码有一些小故障,我无法仅通过 C class 的介绍来修复这些小故障。我正在使用代码编写器。第一个问题:我在 "Tens" 部分 (MSB) 上的计数器并没有停在 9,而是开始显示二进制 10-15。前四位是个位(右),后四位是十位(左)例如:1010 0001
但最大值是 1001 1001
。第二个问题:如果我递减该值,则从零开始,计数器显示 95 而不是 99。
例如:从 0000 0000
开始递减显示 1001 0101
。我尝试使用 if 语句为 MSB 设置一个条件,如果大于 10,则停止,但代码没有 运行。我对代码所做的几乎所有修改都会阻止它正常工作。
#include <msp430.h>
unsigned int dec2bcd(unsigned int num);
void delay(void);
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR = 0xFF;
P2DIR = 0xF0;
unsigned int c;
unsigned int count = 0x00;
while(1){
if((P2IN & BIT0) == BIT0){
count++;
c = dec2bcd(count);
}
else if((P2IN&BIT1) == BIT1){
count--;
c = dec2bcd(count);
}
else if((P2IN&BIT2) == BIT2){
count = 0x00;
c = dec2bcd(count);
}
delay();
P1OUT = c;
}
}
unsigned int dec2bcd(unsigned int num)
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10;
temp = num/10;
tens = temp<<4;
return (tens + ones);
}
void delay(void)
{
volatile unsigned int i, j;
for(i=10000; i>0; i--)
{
for(j=3; j>0; j--){
}
}
}
使用这个有什么限制吗:
if((P2IN & BIT0) == BIT0){
count++;
if (count == 100)
count = 0;
c = dec2bcd(count);
}
else if((P2IN&BIT1) == BIT1){
if (count == 0)
count = 100;
count--;
c = dec2bcd(count);
}
让我们在 countBDC 中计数。
unsigned countBCD = 0;
unsigned count = 0;
while(1){
if((P2IN & BIT0) == BIT0){
count++;
countBCD++;
if ((countBCD & 0xF) >= 0xA) {
// of course can combine these 2 lines
countBCD -= 0xA;
countBCD += 0x10;
if ((countBCD & 0xF0) >= 0xA0) {
countBCD -= 0xA0;
countBCD += 0x100;
...
// similar code for decrement
或者使用BCD增量函数
unsigned BCD_inc(unsigned x) {
unsigned carry = 1;
unsigned mask10 = 10;
unsigned maskNibble = 15;
while (carry) {
x += carry;
if ((x & maskNibble) >= mask10) {
x -= mask10;
mask10 <<= 4;
maskNibble <<= 4;
carry <<= 4;
} else {
carry = 0;
}
}
return x;
}
我现在手边没有 LED 条,但这显示了如何在小数范围内工作,但仅在输出点进行转换。实际值保持在 0..99
范围内(注意当我递减时模数是如何完成的)。然后将值拆分为 BCD 半字节,并将它们组合起来输出。
#include <stdio.h>
void display(int num, char *msg)
{
int lsnib = num % 10; // decimal value of each nibble
int msnib = num / 10;
int ledpatt = (msnib << 4) + lsnib; // recombine as BCD
printf("%02X Expected %s\n", ledpatt, msg);
}
int main(void){
int value;
value = 42;
display (value, "forty two"); // display 42
value = 0;
display (value, "zero"); // display 0
value = 99;
display (value, "ninety nine"); // display 99
value = (value + 1) % 100; // increment from 99
display (value, "zero"); // should display 0
value = (value -1 + 100) % 100; // decrement from 0
display (value, "ninety nine"); // should display 99
return 0;
}
程序输出
42 Expected forty two
00 Expected zero
99 Expected ninety nine
00 Expected zero
99 Expected ninety nine
为什么看到95?
如@Olaf所述,msp430使用16位整数。
当您执行 count = 0u -1
时,计数会自动换行到 65535
;
unsigned int dec2bcd(unsigned int num) // num is now 65535
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10; // 65535%10 = 5
temp = num/10; // 65535/10 = 6553
tens = temp<<4; // what's displayed is by tens is actually the lower
// 4 bits of tens, so tens is 6553%16=9
return (tens + ones);// so the result is 95
}
为什么十可以超过10
同样的问题,因为你的输入大于99。
unsigned int dec2bcd(unsigned int num) // say num is now 100
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10; // 100%10 = 0
temp = num/10; // 100/10 = 10, or 0x0A
tens = temp<<4;
return (tens + ones);// so the result is A0
}
你应该做什么?
在您的代码中,将范围限制为 0-99,您可以选择环绕 (99+1=0, and 0-1=99) 或饱和 (99+1=99, 0) -1=0)。不过你需要什么,你自己写吧:C语言没有提供。
这是解决了我之前遇到的问题的新代码。它可能不是最佳的,但我设法让它发挥作用。我添加了两个创建环绕的 if 语句,并通过实施模数修改了 dec2bcd 转换器。 "tens" 部分中的模数有助于解决显示问题。 谢谢你们帮助我!现在我明白了我的语法错误,感谢你向我展示了我需要关注的范围更广。祝我好运,我希望我能得到额外的荣誉。下次见。
#include <msp430g2553.h>
unsigned int dec2bcd(unsigned int num);
void delay(void);
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR = 0xFF;
P2DIR = 0x00;
unsigned int c;
unsigned int count = 0x00;
//Here are some modified portions to create wrap around
while(1){
if((P2IN & BIT0) == BIT0){
count++;
if(count == (99+1)){
count = 0x00;
}
c = dec2bcd(count);
}
else if((P2IN&BIT1) == BIT1){
count--;
if(count == (0-1)){
count = 0x63;
}
c = dec2bcd(count);
}
else if((P2IN&BIT2) == BIT2){
count = 0x00;
c = dec2bcd(count);
}
delay();
P1OUT = c;
}
}
unsigned int dec2bcd(unsigned int num)
{
unsigned int ones = 0;
unsigned int tens = 0;
unsigned int temp = 0;
ones = num%10;
temp = num/10;
//I used modulus here to get rid of the improper display issue
tens = (temp%10)<<4;
return (tens + ones);
}
void delay(void)
{
volatile unsigned int i, j;
for(i=10000; i>0; i--)
{
for(j=3; j>0; j--){
}
}
}