前言:
记录今天用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码转化成十进制码也一样。
1. static uint8_t BCD2DEC(uint8_t bcd) 2. { 3. return (bcd-(bcd>>4)*6); 4. } 5. 6. static uint8_t DEC2BCD(uint8_t dec) 7. { 8. return (dec+(dec/10)*6); 9. }
这里不太懂……
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转换。
实际应用举例
1. void DS1302_SetTime(void) 2. { 3. DS1302_WriteByte(DS1302_WP, 0x00);//解除芯片写保护 4. DS1302_WriteByte(DS1302_YEAR, DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码 5. DS1302_WriteByte(DS1302_MONTH, DS1302_Time[1]/10*16+DS1302_Time[1]%10); 6. DS1302_WriteByte(DS1302_DATE, DS1302_Time[2]/10*16+DS1302_Time[2]%10); 7. DS1302_WriteByte(DS1302_HOUR, DS1302_Time[3]/10*16+DS1302_Time[3]%10); 8. DS1302_WriteByte(DS1302_MINTUE, DS1302_Time[4]/10*16+DS1302_Time[4]%10); 9. DS1302_WriteByte(DS1302_SECOND, DS1302_Time[5]/10*16+DS1302_Time[5]%10); 10. DS1302_WriteByte(DS1302_DAY, DS1302_Time[6]/10*16+DS1302_Time[6]%10); //星期 11. DS1302_WriteByte(DS1302_WP, 0x80);//此句WP给0x80,打开芯片写保护 12. } 13. 14. void DS1302_ReadTime(void) //此函数读取时钟芯片的数据,写到数组DS1302_Time里 15. { 16. unsigned char Temp; 17. Temp = DS1302_ReadByte(DS1302_YEAR);//读BCD码 18. DS1302_Time[0] = Temp/16*10+Temp%16; 19. Temp = DS1302_ReadByte(DS1302_MONTH);//月 20. DS1302_Time[1] = Temp/16*10+Temp%16; 21. Temp = DS1302_ReadByte(DS1302_DATE); 22. DS1302_Time[2] = Temp/16*10+Temp%16; 23. Temp = DS1302_ReadByte(DS1302_HOUR); 24. DS1302_Time[3] = Temp/16*10+Temp%16; 25. Temp = DS1302_ReadByte(DS1302_MINTUE); 26. DS1302_Time[4] = Temp/16*10+Temp%16; 27. Temp = DS1302_ReadByte(DS1302_SECOND); 28. DS1302_Time[5] = Temp/16*10+Temp%16; 29. Temp = DS1302_ReadByte(DS1302_DAY); 30. DS1302_Time[6] = Temp/16*10+Temp%16; 31. }
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 任意进制转二进制
1. //递归 2. void decToBin(int n) 3. { 4. int a; 5. a = n%2; 6. n /= 2; 7. if(n==0) 8. ; 9. else 10. decToBin(n); 11. cout<<a;