目录
0. 前言:
1. BCD码
2. 算法原理
3. 进制转换
3.1 两位BCD码的转换:
3.2 其他进制转换
3.3 任意进制转二进制
参考资料:
0. 前言:
记录今天用15单片机写DS1302时钟芯片程序的时候遇到的问题
时间显示是这个样的 0 1 2 3 4 5 6 7 8 9 16
9之后突变成16了,没有数据10...11...
why?
读取DS1302时钟芯片的数据是BCD码,需要将BCD码转换成十进制显示
写入数据的时候需要十进制转BCD码
这BCD码,真让人头大
1. BCD码
主要学习什么是BCD码,以及二进制、八进制、十进制、十六进制之间的相互转换
BCD码就是以四位二进制数为一个单位来表示相应的十进制数,因此4位二进制数表示最大的十进制数9(1001),只取十六个数中的十个数。
如下图:
最后一列是BCD码的十进制表示形式,将BCD码按8421法相加即得出最后一栏的数值
图中可以看到0-9位 几个进制的BCD码都是以二进制的正常形式换算,从十开始的BCD码开始不一样了起来。
BCD码:用4位二进制数来表示1位十进制数。 逢九进一
例如:十进制数10的BCD码为0001 0000;
显而易见前四位的 0001 表示的是十进制的十位,0000则就是个位了。十六进制转BCD码也是同理。
例:0001 011(BCD码) 表示13(十进制), 1000 0101(BCD码) 表示85(十进制),0000 1010不合法
2. 算法原理
十进制是逢十进一,而十六进制是逢十六进一,它们之间的每次进位差,所以一个十进制数要转换成BCD码,要先算清多进位的位数,比如,十进制进位了次,每次进位和十六进制进位相比差,所以一共差了,即(BCD)。BCD码转化成十进制码也一样。
static uint8_t BCD2DEC(uint8_t bcd)
{
return (bcd-(bcd>>4)*6);
}
static uint8_t DEC2BCD(uint8_t dec)
{
return (dec+(dec/10)*6);
}
这里不太懂……
3. 进制转换
3.1 两位BCD码的转换:
BCD码转十进制:DEC = BCD / 16 * 10 + BCD % 16 ;
详解:先将BCD的前一位提出BCD/16,再提出BCD后一位BCD%16。最后将两位数整合转换成十进制。多位BCD码同理。
十进制转BCD码:BCD = DEC / 10 * 16 + DEC % 10 ;同上分别提出高低两位,做BCD转换。
实际应用举例
void DS1302_SetTime(void)
{
DS1302_WriteByte(DS1302_WP, 0x00);//解除芯片写保护
DS1302_WriteByte(DS1302_YEAR, DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码
DS1302_WriteByte(DS1302_MONTH, DS1302_Time[1]/10*16+DS1302_Time[1]%10);
DS1302_WriteByte(DS1302_DATE, DS1302_Time[2]/10*16+DS1302_Time[2]%10);
DS1302_WriteByte(DS1302_HOUR, DS1302_Time[3]/10*16+DS1302_Time[3]%10);
DS1302_WriteByte(DS1302_MINTUE, DS1302_Time[4]/10*16+DS1302_Time[4]%10);
DS1302_WriteByte(DS1302_SECOND, DS1302_Time[5]/10*16+DS1302_Time[5]%10);
DS1302_WriteByte(DS1302_DAY, DS1302_Time[6]/10*16+DS1302_Time[6]%10); //星期
DS1302_WriteByte(DS1302_WP, 0x80);//此句WP给0x80,打开芯片写保护
}
void DS1302_ReadTime(void) //此函数读取时钟芯片的数据,写到数组DS1302_Time里
{
unsigned char Temp;
Temp = DS1302_ReadByte(DS1302_YEAR);//读BCD码
DS1302_Time[0] = Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_MONTH);//月
DS1302_Time[1] = Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_DATE);
DS1302_Time[2] = Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_HOUR);
DS1302_Time[3] = Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_MINTUE);
DS1302_Time[4] = Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_SECOND);
DS1302_Time[5] = Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_DAY);
DS1302_Time[6] = Temp/16*10+Temp%16;
}
3.2 其他进制转换
二进制 转 十进制
1110 = 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 0 * 2^0
八进制 转 十进制
36= 3 * 8^1 + 6 * 8^0
十六进制转十进制
0110 = 0 * 16^3 + 1 * 16^2 + 1 * 16^1 + 0 * 16^0
十六进制转二进制转十进制
0x11 = 0001 0001 >>> 0 * 2^7 .... + 1 * 2^4 + 0 + 1 * 2^0
3.3 任意进制转二进制
//递归
void decToBin(int n)
{
int a;
a = n%2;
n /= 2;
if(n==0)
;
else
decToBin(n);
cout<<a;
参考资料:
BCD码以及各进制之间的相互转换
C语言:十进制、BCD码互换
十进制与BCD码转换的算法