uchar BCD(uchar m) { uchar x; x=m>>4; return(x=x*10+(m&=0x0f)); }
时间: 2024-06-06 08:05:18 浏览: 11
这是一个将一个8位二进制数转换为BCD码的函数。具体实现方法是将输入的8位数右移4位,得到高4位,然后将高4位乘以10加上低4位,得到BCD码。最后返回BCD码。但是这段代码有一个小问题,就是在计算低4位时使用了“&=”运算符,应该改成“&”运算符。因为“&=”运算符会对原始数据进行修改,而这里的目的只是想获取低4位的值,所以应该使用“&”运算符。
相关问题
基于51单片机的电子时钟+正反计时代码
以下是基于51单片机的电子时钟+正反计时的代码,你可以参考一下:
```
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCLK = P3^6; //定义DS1302时钟线
sbit RST = P3^5; //定义DS1302复位线
sbit IO = P3^4; //定义DS1302数据线
sbit key1 = P1^0; //定义按键1
sbit key2 = P1^1; //定义按键2
uchar time[8]; //存储时间年月日时分秒
uchar date[11]; //存储日期周几年月日
uchar count1, count2; //正反计时的计数器
uchar timer_mode; //计时器模式,0表示未启动,1表示正计时,2表示反计时
//延时函数
void delay(uint z)
{
uint x,y;
for(x=z; x>0; x--)
for(y=110; y>0; y--);
}
//DS1302时钟信号产生函数
void ds1302_clock()
{
SCLK = 0;
_nop_();
_nop_();
SCLK = 1;
}
//DS1302写入函数
void ds1302_write(uchar dat)
{
uchar i;
for(i=0; i<8; i++)
{
IO = dat & 0x01;
dat >>= 1;
ds1302_clock();
}
}
//DS1302读取函数
uchar ds1302_read()
{
uchar i, dat = 0;
for(i=0; i<8; i++)
{
dat >>= 1;
if(IO)
dat |= 0x80;
ds1302_clock();
}
return dat;
}
//DS1302初始化函数
void ds1302_init()
{
uchar i;
RST = 0;
delay(2);
RST = 1;
delay(2);
ds1302_write(0x8e);
ds1302_write(0x00);
for(i=0; i<7; i++)
{
ds1302_write(time[i]);
}
}
//读取DS1302时间函数
void ds1302_read_time()
{
uchar i;
ds1302_write(0xbf);
for(i=0; i<7; i++)
{
time[i] = ds1302_read();
ds1302_clock();
}
}
//读取DS1302日期函数
void ds1302_read_date()
{
uchar i;
ds1302_write(0xbe);
for(i=0; i<7; i++)
{
date[i] = ds1302_read();
ds1302_clock();
}
}
//将数字转换为BCD码
uchar num_to_bcd(uchar num)
{
uchar bcd;
bcd = (num / 10) << 4;
bcd |= num % 10;
return bcd;
}
//将BCD码转换为数字
uchar bcd_to_num(uchar bcd)
{
uchar num;
num = (bcd >> 4) * 10;
num += bcd & 0x0f;
return num;
}
//显示时间函数
void show_time()
{
uchar hour, minute, second;
hour = bcd_to_num(time[2]);
minute = bcd_to_num(time[1]);
second = bcd_to_num(time[0]);
printf("%02d:%02d:%02d\r", hour, minute, second);
}
//显示日期函数
void show_date()
{
uchar year, month, day, week;
year = bcd_to_num(date[6]);
month = bcd_to_num(date[4]);
day = bcd_to_num(date[3]);
week = bcd_to_num(date[2]);
printf("%d-%02d-%02d 星期%d\r", year, month, day, week);
}
//按键扫描函数
void key_scan()
{
if(key1 == 0)
{
delay(10);
if(key1 == 0)
{
timer_mode = 1; //设置为正计时模式
count1 = 0; //计数器清零
count2 = 0;
delay(100);
while(key1 == 0); //等待按键释放
}
}
if(key2 == 0)
{
delay(10);
if(key2 == 0)
{
timer_mode = 2; //设置为反计时模式
count1 = 0; //计数器清零
count2 = 0;
delay(100);
while(key2 == 0); //等待按键释放
}
}
}
//计时器函数
void timer()
{
if(timer_mode == 1) //正计时模式
{
count1++; //计数器加1
if(count1 == 60) //一分钟到了
{
count1 = 0;
count2++; //计数器加1
}
}
else if(timer_mode == 2) //反计时模式
{
count1++; //计数器加1
if(count1 == 60) //一分钟到了
{
count1 = 0;
count2--; //计数器减1
}
}
}
void main()
{
TMOD = 0x01; //设置定时器0为模式1
TH0 = 0xfc; //设置定时器初值
TL0 = 0x67;
TR0 = 1; //启动定时器0
ET0 = 1; //允许定时器0中断
EA = 1; //开启总中断
ds1302_init(); //DS1302初始化
while(1)
{
ds1302_read_time(); //读取时间
ds1302_read_date(); //读取日期
show_time(); //显示时间
show_date(); //显示日期
key_scan(); //按键扫描
timer(); //计时器
}
}
//定时器0中断函数
void timer0() interrupt 1
{
TH0 = 0xfc; //重新设置初值
TL0 = 0x67;
ds1302_write(0x80); //写入DS1302控制字节
ds1302_write(num_to_bcd(count1)); //写入秒
ds1302_write(num_to_bcd(count2)); //写入分(正计时)或剩余分(反计时)
ds1302_write(0x00); //写入小时,不用更新
ds1302_write(0x00); //写入日,不用更新
ds1302_write(0x00); //写入月,不用更新
ds1302_write(0x00); //写入年,不用更新
ds1302_write(0x8e); //打开写保护
ds1302_write(0x00);
}
```
这段代码实现了基于51单片机的电子时钟+正反计时功能,其中使用了DS1302实时时钟模块和LCD屏幕。你可以根据自己的需要进行修改和调整。
C语言实现,数列求和,已知数列1/1,2/1,3/2,5/3,8/5,51单片机P1口连接2个BCD数码管,分别显示十位和个位;外部中断0引脚连接按键, (1)按1下按键,求取数列前5项的和; (2)再按1下按键,求取数列前10项的和; (3)再按1下按键,求取数列前20项的和; (4)再次按下按键,恢复(1)的操作。 利用keil5编程,实现上述功能,求出数列之和,但只需要显示数列和的整数部分,两位4位的BCD数码管按十进制方式显示,用一个延时函数,一个中断函数,一个显示函数,一个main函数实现
以下是代码实现:
```c
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
uint fibonacci(uint n);
void delay(uint t);
void display(uint num);
uchar flag = 0;
void main()
{
EA = 1; // 全局中断使能
EX0 = 1; // 外部中断0使能
IT0 = 1; // 下降沿触发
while(1)
{
if(flag == 1)
{
uint sum = 0;
for(uint i = 1; i <= 5; i++)
{
sum += fibonacci(i);
}
display(sum);
flag = 0;
}
else if(flag == 2)
{
uint sum = 0;
for(uint i = 1; i <= 10; i++)
{
sum += fibonacci(i);
}
display(sum);
flag = 0;
}
else if(flag == 3)
{
uint sum = 0;
for(uint i = 1; i <= 20; i++)
{
sum += fibonacci(i);
}
display(sum);
flag = 0;
}
}
}
uint fibonacci(uint n)
{
if(n == 1 || n == 2)
{
return n-1;
}
else
{
return fibonacci(n-1) + fibonacci(n-2);
}
}
void delay(uint t)
{
while(t--);
}
void display(uint num)
{
uchar shiwei = num / 10;
uchar gewei = num % 10;
P1 = (shiwei << 4) | gewei;
delay(500);
P1 = 0x00;
delay(500);
}
void external0() interrupt 0
{
flag++;
if(flag > 3)
{
flag = 1;
}
delay(1000); // 消除按键抖动
}
```
其中,fibonacci()函数用于求斐波那契数列的第n项,delay()函数用于延时,display()函数用于将数字转换为BCD码并显示在数码管上,external0()函数是外部中断0的中断服务函数,用于切换计算数列的项数。
需要注意的是,由于数列求和的结果可能会超出两位数,因此在display()函数中只显示了数列和的整数部分,忽略了小数部分。如果需要完整的结果,可以使用浮点数计算,但需要注意单片机的运算速度和存储空间限制。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![doc](https://img-home.csdnimg.cn/images/20210720083327.png)
![](https://img-home.csdnimg.cn/images/20210720083646.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![doc](https://img-home.csdnimg.cn/images/20210720083327.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)