52单片机设计时钟(串口控制)

实现目标

单片机时钟正常工作,数码管显示时分秒。电脑和单片机串行通信,通过电脑串口助手,任意修改设置单片机的时钟值。

实现的流程框图

52单片机设计时钟(串口控制)_第1张图片

运用到的原理有

定时器/计数器

定时器/计数器由高8位和低8位两个寄存器组成,本质是加1计数器。加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;另一个是T0或T1引脚输入的外部脉冲源,每来一个脉冲计数器加1,当加到计数器全为1时,再输入一个脉冲就使计数器回零,且计数器的溢出使TCON寄存器中的TF0或TF1置1,向CPU发出中断请求(定时器/计数器中断允许时)。如果定时器/计数器工作于定时器模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。设置为定时器模式时,加1计数器是对内部机器周期计数(1个机器周期等于12个振荡周期,即计数频率为晶振频率的1/12)。计数值N乘以机器周期Tcy就是定时时间t 。

中断

中断是为使单片机具有对外部或内部随即发生的事件实时处理而设置的, 51单片机内部一共有5个中断源,也就是说,有五种情况发生时,会使单片机去处理中断程序。对于单片机来讲,中断是指CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理(中断发生);CPU暂时停止当前的工作(中断响应),转去处理事件B(中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。

引起CPU中断的根源,称为中断源,中断源向CPU提出中断请求,CPU暂时中断原来的事务A,转去处理事件B,对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统(中断机构)。

数码管动态扫描

在这里要实现数码管每一位显示的数字不同,我们可以使用视觉暂留的方法,在很快的时间内,不断的将数码管上面的显示进行切换,如现在第一位上显示数字1之后其它位上不显示,再在第二位上显示数字2其它位上不显示,这样不断的来回切换,便能实现数码管显示12,同理便可在数码管上显示此时的瞬间的时间数值,具体实现在代码中可以看到。在此基础上,在程序中,一个大循环中不断的在数码管上显示数字,利用中断实现数字的变动,便能实现数码管上的数字,随着时间的变化而显示不同的数字。

串行口通信原理

通信有并行和串行两种方式。在单片机系统以及现代单片机测控系统中,信息的交换多采用串行通信方式。串行通信是将数据字节分成一位一位的形式在一条传输线上逐个地传送,此时只需要一条数据线,外加一条公共信号地线和若干控制信号线。因为一次只能传送一位,所以对于一个字节的数据,至少要分8位才能传送完毕。

串行通信又有两种方式:异步串行通信和同步串行通信。

异步串行通信是指通信的发送和接受设备使用各自的时钟控制数据的传送和接收过程。在单片机和单片机之间,单片机和计算机之间通信时,通常采用异步串行通信方式。同步通信要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。

实验器材

硬件:GTX TX-1C开发板

软件:Windows操作系统,Keil软件,STC烧写软件,串口调试助手。

最终效果

52单片机设计时钟(串口控制)_第2张图片

实现代码 

#include
#include

#define uchar unsigned char
#define uint unsigned int

sbit b5 = P3 ^ 7;
sbit u1 = P2 ^ 6;
sbit u2 = P2 ^ 7;
sbit P36 = P3 ^ 6; //按键中断

unsigned char code table[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xff };
unsigned char code opt[] = { 0xff,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };
int _1, _2, _3, _4, _5, _6;//数码管的数字
int	a, b, c, d, e, f;//判断数码管每位是否亮灭
unsigned int num = 20, flag_time, flag_guangbiao = 6;
uchar temp, first = 1;

//延迟快
void delay1() {
	unsigned int j, i;
	for (i = 20; i > 0; i--)
		for (j = 10; j > 0; j--);
}
//延迟
void delay(int i) {
	unsigned int j;
	for (; i > 0; i--)
		for (j = 110; j > 0; j--);
}

int key() {
	if (b5 == 0) {
		delay(5);
		if (b5 == 0) {
			while (!b5);
			return 1;
		}
	}
	return 0;
}

void init_chuanko() {
	TMOD = 0x21;
	TH1 = 0xfd;
	TL1 = 0xfd;
	TR1 = 1;
	REN = 1;
	SM0 = 0;
	SM1 = 1;
	EA = 1;
	ES = 1;
}

void init_display() {
	_1 = 0; _2 = 0; _3 = 0; _4 = 0; _5 = 2; _6 = 1;
	a = 1; b = 1; c = 1; d = 1; e = 1; f = 1;
}

void init_zhongduan() {
	TMOD = 0x01;
	TH0 = (65536 - 45872) / 256; TH0 = (65536 - 45872) % 256;
	TH1 = (65536 - 45872) / 256; TH1 = (65536 - 45872) % 256;
	EA = 1; ET0 = 1; TR0 = 1;
}

void init_anjian() {
	P36 = 0;
	EA = 1;
	IT0 = 1;
	TCON = 0x01;
	EX0 = 1;//设置按键中断
}

void display(int a, int b, int c, int d, int e, int f, int _1, int _2, int _3, int _4, int _5, int _6) {
	if (a == 1) {
		u1 = 1;
		P0 = table[_1];
		u1 = 0;
		P0 = 0xff;
		u2 = 1;
		P0 = opt[1];
		u2 = 0;
		delay1();
	}

	if (b == 1) {
		u1 = 1;
		P0 = table[_2];
		u1 = 0;
		P0 = 0xff;
		u2 = 1;
		P0 = opt[2];
		u2 = 0;
		delay1();
	}

	if (c == 1) {
		u1 = 1;
		P0 = table[_3];
		u1 = 0;
		P0 = 0xff;
		u2 = 1;
		P0 = opt[3];
		u2 = 0;
		delay1();
	}

	if (d == 1) {
		u1 = 1;
		P0 = table[_4];
		u1 = 0;
		P0 = 0xff;
		u2 = 1;
		P0 = opt[4];
		u2 = 0;
		delay1();
	}

	if (e == 1) {
		u1 = 1;
		P0 = table[_5];
		u1 = 0;
		P0 = 0xff;
		u2 = 1;
		P0 = opt[5];
		u2 = 0;
		delay1();
	}

	if (f == 1) {
		u1 = 1;
		P0 = table[_6];
		u1 = 0;
		P0 = 0xff;
		u2 = 1;
		P0 = opt[6];
		u2 = 0;
		delay1();
	}

}

//时间中断
void jishi() interrupt 1{
	num--;
	if (num == 0) {
		num = 20;
		flag_time = 1;
	}
}

void main() {

	init_anjian();

	while (1) {

		if (key()) {

			init_zhongduan();
			init_display();
			init_chuanko();

			while (1) {

				u2 = 1;
				P0 = 0xff;
				u2 = 0;
				P0 = 0x0;
				u1 = 1;
				P0 = 0x0;
				u1 = 0;
				if (key()) {
					ET0 = 0; TR0 = 0;
					TR1 = 0;
					REN = 0;
					ES = 0;
					break;
				}

				display(a, b, c, d, e, f, _1, _2, _3, _4, _5, _6);

				if (flag_time == 1) {
					_1++;
					if (_1 > 9) {
						_1 = 0;
						_2++;
						if (_2 > 5) {
							_2 = 0;
							_3++;
							if (_3 > 9) {
								_3 = 0;
								_4++;
								if (_4 > 5) {
									_4 = 0;
									_5++;
									if (_5 > 9 && _6 < 2 || _5>3 && _6 == 2) {
										_5 = 0;
										_6++;
										if (_6 > 2) {
											_6 = 0;
										}
									}
								}
							}
						}
					}
					flag_time = 0;
				}



			}
		}
	}
}

void ser() interrupt 4{
	RI = 0;
	if (first == 0) {
		temp = SBUF;
		temp -= '0';
		if (flag_guangbiao == 6) { _6 = temp; }
		else if (flag_guangbiao == 5) { _5 = temp; }
		else if (flag_guangbiao == 4) { _4 = temp; }
		else if (flag_guangbiao == 3) { _3 = temp; }
		else if (flag_guangbiao == 2) { _2 = temp; }
		else if (flag_guangbiao == 1) { _1 = temp; }
		flag_guangbiao--;
		if (flag_guangbiao == 0) { flag_guangbiao = 6; }
	}
	else { first = 0; }
}

void exter0() interrupt 0
{
	init_display();
}

由于初学c语言和单片机,因此代码有的地方写得的确不好,很冗余,望理解。

你可能感兴趣的:(单片机,stm32,c语言)