大家好,欢迎来到IT知识分享网。
目录
0. 前言:
记录今天用15单片机写DS1302时钟芯片程序的时候遇到的问题
why?
读取DS1302时钟芯片的数据是BCD码,需要将BCD码转换成十进制显示
写入数据的时候需要十进制转BCD码
这BCD码,真让人头大
1. BCD码
主要学习什么是BCD码,以及二进制、八进制、十进制、十六进制之间的相互转换
BCD码就是以四位二进制数为一个单位来表示相应的十进制数,因此4位二进制数表示最大的十进制数9(1001),只取十六个数中的十个数。
如下图:
十进制 | 二进制 | 十六进制 | BCD码 | BCD – 十进制 |
0 | 0000 | 0 | 0000 | 0 |
1 | 0001 | 1 | 0001 | 1 |
2 | 0010 | 2 | 0010 | 2 |
3 | 0011 | 3 | 0011 | 3 |
4 | 0100 | 4 | 0100 | 4 |
5 | 0101 | 5 | 0101 | 5 |
6 | 0110 | 6 | 0110 | 6 |
7 | 0111 | 7 | 0111 | 7 |
8 | 1000 | 8 | 1000 | 8 |
9 | 1001 | 9 | 1001 | 9 |
10 | 1010 | A | … | 16 |
11 | 1011 | B | … | 17 |
12 | 1100 | C | … | 18 |
13 | 1101 | D | … | 19 |
14 | 1110 | E | … | 20 |
15 | 1111 | F | … | 21 |
最后一列是BCD码的十进制表示形式,将BCD码按8421法相加即得出最后一栏的数值
图中可以看到0-9位 几个进制的BCD码都是以二进制的正常形式换算,从十开始的BCD码开始不一样了起来。
BCD码:用4位二进制数来表示1位十进制数。 逢九进一
例:0001 011(BCD码) 表示13(十进制), 1000 0101(BCD码) 表示85(十进制),0000 1010不合法
BCD码 — 常用的数字编码形式。可能我们在学校经常使用二进制和十六进制的数字表达形式。然而大多数情况下我们都是需要和十进制数进行转化来进行数字的表达,因为我们社会普遍习惯使用十进制。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免去使计算机作浮点运算时所耗费的时间。
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码转换的算法
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/142757.html