二、你可能还没有理解串行通信的含义,与并行通信不同,串行通信只用到两根或三根线,具体分为:
1.UART(异步)串口:三根线——TXD发射、RXD接收、GND地线
2.SPI(同步)串口:三根线——SDI数据入、SDO数据出、SCK时钟线
3.I2C:两根线——SDA数据出入、SCK时钟线
无论是哪种串行通信,数雀卖据都是通过一根线进行传递的,你可以想象一个8位的字节顷银逗要通过串口传递,一定是根据某种协议(时钟),按照一定的顺序格式逐位进行的,而具体形式就是0或1,在这个tlc0831的读取程序中,是通过单片机的I/O口模拟SPI时序来进行数据读取的,按照SPI协议在每个时钟信号的下降沿,就有一个数据位传送过来。
而根据tlc0831的工作、读取时序要求(如图),在CS被置0(启动一次转换)之后,读取数据之前,需要有一段建立时间(settling time),在这段时间内需要外部持续提供一定频率的时钟信号。
说到这里你应该就能读懂整个程序了。
ADC0831和ADC0832是8位串行I/OA/D转换器。ADC0831是单通道,有输入Vin+和Vin-,有参考电源REF,只有串行数据输出DO。ADC0832是双通道,有仿闭通道CH0和CH1,参凳闭考电压REF接VCC,有串行数据输入DI和串行枣大裂数据输出DO。#include<reg51.h>#include<intrins.h>
#include <absacc.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
#define BUSY 0x80 // LCD
#define DATAPORT P0 // 参
sbit LCM_RS=P2^0// 数
sbit LCM_RW=P2^1// 配
sbit LCM_EN=P2^2// 置
sbit reset=P3^7
sbit bj=P3^0
sbit time_start=P3^2
sbit time_over=P3^3
sbit EOC=P2^3//OE=1,输出转换得到的数据;OE=0,输出数据线呈高阻状态。
sbit START=P2^4//START为转换启动信号。当START上跳沿时,所有内部寄存器清零;下跳沿时,开始顷逗高进行A/D转换;在转换期间,ST应保持低电平。
sbit OE =P2^5//EOC为转换结束信号。当EOC为高电平时,表明转换结束;否则,表明正在进行A/D转换。
sbit AD_ALE=P2^6//ad 转换
sbit CLK=P2^7
unsigned long int getdata
void ADC0808()
uchar code str0[]={"Throb: "}
uchar code str1[]={"Time:" }
void delay(uint k)//延时
void lcd_wait()//LCM忙检测
void WriteCommandLCM(uchar WCLCM,uchar BusyC)//写指令到LCM子函数
void WriteDataLCM(uchar WDLCM)//写数据到LCM子函数
void DisplayOneChar(uchar X,uchar Y,uchar DData)//显示指定坐标的一个字符子函数
void DisplayListChar(uchar X,uchar Y,uchar code *DData)/雀尺/显示指定坐标的一串字符子函数
void initLCM( void)//LCD初始化子程序
uchar m=0
uint counter=0,counter_0=0
uchar second_0=0
uint totle_1
float totle_0
void main()
{
uint i,j,k
TMOD=0x02
TL0=0xfe
TH0=0xfe//AD频率
TR0=1
ET0=1
TH1=0x60
TL1=0x78//定时5ms
ET1=1
PX1=1
EX0=1
IT0=1
EX1=1
IT1=1
EA=1
delay(100)//系统延时500ms启动
initLCM( )
WriteCommandLCM(0x01,1)//清显示屏
DisplayListChar(0,0,str0)
DisplayListChar(0,1,str1)
AD_ALE=0
START=0
OE=0
while(1)
{
ADC0808()
//v=getdata
if(getdata>=300&&getdata<400)
{
delay(60)
if(getdata>=300&&getdata<400)
{
counter++
if(m==1)
{
PT1=1
TR1=1
m=0
}
}
}
// DisplayOneChar(7,0,0x30+getdata/100)
// DisplayOneChar(8,0,0x30+getdata%10)
// DisplayOneChar(9,0,0x30+getdata/指掘10%10)
if(counter<100)
{
DisplayOneChar(8,0,0x30+counter/10)
DisplayOneChar(9,0,0x30+counter%10)
}
if(counter>=100)
{
DisplayOneChar(7,0,0x30+counter/100)
DisplayOneChar(8,0,0x30+counter/10%10)
DisplayOneChar(9,0,0x30+counter%10)
}
if(second_0>59)
{ second_0=0}
DisplayOneChar(7,1,0x30+second_0%10)
DisplayOneChar(6,1,0x30+second_0/10)
if(reset==0)
{
counter=0
counter_0=0
second_0=0
totle_0=0
totle_1=0
bj=0
}
totle_1=(int)totle_0
DisplayOneChar(9,1,0x30+totle_1/100)
DisplayOneChar(10,1,0x30+totle_1/10%10)
DisplayOneChar(11,1,0x30+totle_1%10)
DisplayOneChar(12,1,'/')
DisplayOneChar(13,1,'m')
DisplayOneChar(14,1,'i')
DisplayOneChar(15,1,'n')
if(totle_1>120)
{
for(k=0k<100k++)
{
for(i=0i<25i++)
bj=0
for(j=0j<25j++)
bj=1
if(reset==0)
{
counter=0
counter_0=0
second_0=0
totle_0=0
totle_1=0
bj=0
}
}
}
if(totle_1<40&&totle_1>0)
{
for(k=0k<100k++)
{
for(i=0i<25i++)
bj=0
for(j=0j<25j++)
bj=1
if(reset==0)
{
counter=0
counter_0=0
second_0=0
totle_0=0
totle_1=0
bj=0
}
}
}
}
}
/****************外部中断0*******************/
void intr0_int() interrupt 0 using 3
{
m=1
}
/****************外部中断1*******************/
void intr1_int() interrupt 2 using 3
{
PT1=0
TR1=0
totle_0=(float)counter/second_0*60
}
/****************定时中断0*******************/
void timer0_int() interrupt 1 using 1
{
CLK=~CLK
}
/****************定时中断1*******************/
void timer1_int() interrupt 3 using 2
{
TH1=0x60
TL1=0x78
counter_0++
if(counter_0==190)
{
counter_0=0
second_0++
}
}
/*********延时K*1ms,12.000mhz**********/
void delay(uint k)
{
uint i,j
for(i=0i<ki++)
for(j=0j<100j++)
}
/***********lcm内部等待函数*************/ //从这里到AD前面都是 LCD的驱动程序
void lcd_wait(void)
{
DATAPORT=0xff//读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
LCM_EN=1
LCM_RS=0
LCM_RW=0
LCM_RW=1
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
while(DATAPORT&BUSY)
{ LCM_EN=0
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
LCM_EN=1
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
}
LCM_EN=0
}
/**********写指令到LCM子函数************/
void WriteCommandLCM(uchar WCLCM,uchar BusyC)
{
if(BusyC)
lcd_wait()
DATAPORT=WCLCM
LCM_RS=0// 选中指令寄存器
LCM_RW=0
LCM_RW=0// 写模式
LCM_EN=1
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
LCM_EN=0
}
/**********写数据到LCM子函数************/
void WriteDataLCM(uchar WDLCM)
{
lcd_wait( )//检测忙信号
DATAPORT=WDLCM
LCM_RS=1// 选中数据寄存器
LCM_RW=0// 写模式
LCM_EN=1
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
_nop_()
LCM_EN=0
}
/****显示指定坐标的一个字符子函数****/
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
Y&=0x01
X&=0x0f
if(Y)
X|=0x40//若y为1(显示第二行),地址码+0X40
X|=0x80//指令码为地址码+0X80
WriteCommandLCM(X,1)
WriteDataLCM(DData)
}
/*******显示指定坐标的一串字符子函数*****/
void DisplayListChar(uchar X,uchar Y,uchar code *DData)
{
uchar ListLength=0
Y&=0x01
X&=0x0f
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength])
ListLength++
X++
}
}
/**********LCM初始化子函数***********/
void initLCM( )
{
LCM_EN=0
DATAPORT=0
delay(15)
WriteCommandLCM(0x38,0)//三次显示模式设置,不检测忙信号
delay(5)
WriteCommandLCM(0x38,0)
delay(5)
WriteCommandLCM(0x38,0)
delay(5)
WriteCommandLCM(0x38,1)//8bit数据传送,2行显示,5*7字型,检测忙信号
WriteCommandLCM(0x08,1)//关闭显示,检测忙信号
WriteCommandLCM(0x01,1)//清屏,检测忙信号
WriteCommandLCM(0x06,1)//显示光标右移设置,检测忙信号
WriteCommandLCM(0x0c,1)//显示屏打开,光标不显示,不闪烁,检测忙信号
}
/*****************读电压**********************/ //AD转换的驱动程序,就这一部分
void ADC0808()
{
AD_ALE=1//锁存输入通道
_nop_()_nop_()
START=0//驱动AD转换
START=1
AD_ALE=0
_nop_()_nop_()
START=0//保持低电平
while(EOC==0)//等待AD转换结束
// TR0=0//AD转换结束时先停止T0
P1=0xff
OE=1//转换结束,允许AD值输出
getdata=P1//读出AD值.
OE=0//禁止输出
getdata=(unsigned long int)((unsigned long int)(getdata*500)/255)//转换成电压
// TR0=1//重新启动T0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)