微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 串行口通信 单片机在数码管显示AD采集值

串行口通信 单片机在数码管显示AD采集值

时间:11-22 来源:互联网 点击:
一. 程序功能

单片机上电后等待从上位机串口发送来的命令(波特率为9600bps),同时在数码管的前三位以十进制显示 AD采集来的数值。

1)当收到以十六进制发送来的01后,向上位机发送字符串“Turn on ad!”,同时间隔 一秒读取AD的值,然后把AD转换过来的数表示成实际电压值(浮点数),并且从串口发 送给上位机,形式如“The voltage is 3.398438V”发送周期也是一秒一次。

2)当收到02时,向上位机发送“Turn off ad!”并停止发送电压值

3)收到其他数时显示“Error!”

二. 程序源码

1)法1

#include

#include

#include

#define uchar unsigned char

#define uint unsigned int

sbit dula = P2 ^ 6; //申请U1锁存器的锁存端

sbit wela = P2 ^ 7; //申请U1锁存器的锁存端

sbit adwr = P3 ^ 6; //定义AD的WR端口

sbit adrd = P3 ^ 7; //定义AD的RD端口

uchar flag, flag_uart, flag_time, flag_on;

uchar a, i, t0_num, ad_val;

float ad_vo;

//数码管的编码数组

uchar code table[] = {

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71

};

void delayms(uint xms);

void init();

void display(uchar value);

uchar get_ad();

void main()

{

//初始化

init();

//为了节省IO端口,ADC0804的片选端CS连接U2锁存器的Q7输出端

//即位选时,P0的最高位

//于是通过位选时对P0赋值置CSAD为0,选通后,以后不必在管

wela = 1;

P0 = 0x7f;

wela = 0;

while (1)

{

//若检测到flag_uart为1,说明串口已经执行过串口中断服务程序, 即收到了数据

if (flag_uart == 1)

{

//手动将flag_uart清0,方便标志位检测

flag_uart = 0;

//检测到收到数据后,先将ES清0,原因是接下来要发送数据,若不关闭串口,

//发送完数据后,单片机会重新申请串口中断flag_uart又为1,又再次发送,一直反复

ES = 0;

//由于下面switch中需要调用puts,printf,在单片机的puts,printf中需要对TI是否为1

//进行检测,就是需要等待TI为1才会将字符发送出去,否则一直等待下去

//所以这里需要先将TI置为1

TI = 1;

//根据执行串口中断后获取的flag_on的值执行相应的动作

switch(flag_on)

{

case 0:

puts("Turn on ad!\n");

TR0 = 1; //开启计数器0

break;

case 1:

printf("Turn off ad!\n");

TR0 = 0; //关闭计数器0

break;

case 2:

puts("Error!\n");

break;

}

//等待发送完毕,因为发送完毕后TI会由硬件清0

while (!TI);

//手动TI清0

TI = 0;

//重新开启串口中断

ES = 1;

}

//通过flag_time判断时间是否到1s, 从而去获取AD转换的值

if (flag_time == 1)

{

//手动将flag_time清0,方便下次检测

flag_time = 0;

//获取AD转换的值

ad_val = get_ad();

//获取浮点数表示的AD实际采集到的电压值

ad_vo = (float)ad_val*5.0/256.0;

//关闭串口中断

ES = 0;

//下面要调用printf,所以将TI置1, 原因见上面

TI = 1;

printf("The voltage is %fV\n", ad_vo);

//检测发送是否完成

while (!TI);

//手动TI清0

TI = 0;

//开启串口中断

ES = 1;

}

//数码管上显示AD转化的值

display(ad_val);

}

}

void delayms(uint xms)

{

uint i, j;

for (i = xms; i > 0; i--)

for (j = 110; j > 0; j--)

;

}

void init()

{

//设定T1定时器工作方式2, T0定时器工作方式1

TMOD = 0x21;

//为T0定时器装入初值

TH0 = (65536 - 50000) / 256;

TL0 = (65536 - 50000) % 256;

//为T1定时器装入初值

TH1 = 0xfd;

TL1 = 0xfd;

//ET1 = 1; 这里不需要开启定时器1中断,因为定时器1工作在方式2,为8位自动重装方式,进入中断也无事可做

//启动T1定时器

TR1 = 1;

//开启定时器0中断

ET0 = 1;

//启动定时器0

//TR0 = 1; TR0的初始化放在主函数的while中,方便检测到串口发送数据后的1s延时,即延时1s从串口发送完数据开始

//设定串口工作方式

//11位异步收发,含9位数据,波特率可变,且由定时器1溢出率控制

SM0 = 1;

SM1 = 1;

//容许串口中断

REN = 1;

//开启总中断

EA = 1;

//开启串口中断

ES = 1;

}

void display(uchar num)

{

uchar bai, shi, ge;

bai = num / 100;

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top