1)将采集的电压值显示在数码管上(1通道,0-5V,保留1位小数,比如4.2)
2)通过串口将测量电压值传递给PC。
传送数据格式:发送16进制数或其他。
3)当电压大于4.5V时,继电器1动作;当电压小于0.5V时,继电器2动作。
所需硬件: 1.单片机实验开发板B
2.杜邦头插线
3.DS18B20
4.STC89C51RC单片机
所需软件: 1. Keil C51 V8.08或Keil_uv3 绿色版本
2.STC单片机ISP下载编程软件
TLC0832资料
/******************************************************************
** 单片机与PC串口通信1
** 晶 振 频 率:11.0592M
** 线路->单片机实验开发板B
******************************************************************/
#include
#include
/****************************TLC0832端口定义*********************************************/
sbit ADC_CLK=P1^2;
sbit ADC_DO=P1^3;
sbit ADC_DI=P1^4;
sbit ADC_CS=P1^7;
/****************************数码显示 键盘接口定义****************************************/
sbit PS0=P2^4;//数码管个位
sbit PS1=P2^5;//数码管十位
sbit PS2=P2^6;//数码管百位
sbit PS3=P2^7;//数码管千位
sfr P_data=0x80;//P0口为显示数据输出口
sbit P_K_L=P2^2;//键盘列
sbit JDQ1=P2^0;//继电器1控制
sbit JDQ2=P2^1;//继电器2控制
unsigned char tab[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0,0x9c,0x7a,0x9e,0x8e};//字段转换表
unsigned char adc_change(unsigned char a);//操作TLC0832
unsigned int htd(unsigned int a); //进制转换函数
void display(unsigned int a);//显示函数
void delay(unsigned int);//延时函数
void main(void)
{
unsigned int a,temp;
TMOD=0x20; //定时器1--方式2
TL1=0xfa;
TH1=0xfa; //11.0592MHZ晶振,波特率为4800
SCON=0x50; //方式1
TR1=1; //启动定时
while(1)
{
temp=adc_change('0')*10*5/255;
for(a=0;a<20;a++)//显示,兼有延时的作用
display(htd(temp));
SBUF=(unsigned char)(temp>>8); //将测量结果发送给PC
while(TI!=1);
TI=0;
SBUF=(unsigned char)temp;
while(TI!=1);
TI=0; if(temp>45)
JDQ1=0;//继电器1动作
else
JDQ1=1;//继电器1复位
if(temp<5)
JDQ2=0;//继电器2动作
else
JDQ2=1;//继电器1复位
}
}
/**************************数码管显示函数**************************/
/*函数原型:void display(void)
/*函数功能:数码管显示
/*输入参数:无
/*输出参数:无
/*调用模块:delay()
/*建立时间:2005/11/14
/*作者:站长
/******************************************************************/
void display(unsigned int a)
{
bit b=P_K_L;
P_K_L=1;//防止按键干扰显示
P_data=tab[a&0x0f];//显示小数点后第1位
PS0=0;
PS1=1;
PS2=1;
PS3=1;
delay(200);
P_data=tab[(a>>4)&0x0f]|0x01; //显示个位
PS0=1;
PS1=0;
delay(200);
P_data=tab[(a>>8)&0x0f];//显示十位
PS1=1;
PS2=0;
delay(200);
//P_data=tab[(a>>12)&0x0f];//显示百位
PS2=1;
//PS3=0;
//delay(200);
//PS3=1;
P_K_L=b;//恢复按键
P_data=0xff;//恢复数据口
}
/*************************************************************************************************
; 函数名称: adc_change
; 功能描述: TI公司8位2通adc芯片TLC0832的控制时序
; 形式参数: config(无符号整型变量)
; 返回参数: a_data
; 局部变量: m、n
; 调用模块:
; 备 注:
**************************************************************************************************/
unsigned char adc_change(unsigned char config)//操作TLC0832
{
unsigned char i,a_data=0;
ADC_CLK=0;
_nop_();
ADC_DI=0;
_nop_();
ADC_CS=0;
_nop_();
ADC_DI=1;
_nop_();
ADC_CLK=1;
_nop_();
ADC_CLK=0;
if(config=='0')
{
ADC_DI=1;
_nop_();
ADC_CLK=1;
_nop_();
ADC_DI=0;
_nop_();
ADC_CLK=0;
}
else if(config=='1')
{
ADC_DI=1;
_nop_();
ADC_CLK=1;
_nop_();
ADC_DI=1;
_nop_();
ADC_CLK=0;
}
ADC_CLK=1;
_nop_();
ADC_CLK=0;
_nop_();
ADC_CLK=1;
_nop_();
ADC_CLK=0;
for(i=0;i<8;i++)
{
a_data<<=1;
ADC_CLK=0;
a_data+=(unsigned char)ADC_DO;
ADC_CLK=1;
}
ADC_CS=1;
ADC_DI=1;
return a_data;
}
/**************************十六进制转十进制函数**************************/
/*函数原型:uint htd(uint a)
/*函数功能:十六进制转十进制
/*输入参数:要转换的数据
/*输出参数:转换后的数据
/*调用模块:无
/*建立时间:2005/11/14
/*作者:站长
/******************************************************************/
unsigned int htd(unsigned int a)
{
unsigned int b,c;
b=a%10;
c=b;
a=a/10;
b=a%10;
c=c+(b<<4);
a=a/10;
b=a%10;
c=c+(b<<8);
a=a/10;
b=a%10;
c=c+(b<<12);
return c;
}
/*******************************延时函数*********************************/
/*函数原型:delay(unsigned int delay_time)
/*函数功能:延时函数
/*输入参数:delay_time (输入要延时的时间)
/*输出参数:无
/*调用模块:无
/*建立时间:2005/10/21
/*作者:站长
/**********************************************************************/
void delay(unsigned int delay_time) //延时子程序
{for(;delay_time>0;delay_time--)
{}
}
keil工程文件打包下载 chuankou2.rar
/******************************************************************
** 单片机与PC串口通信2
** 晶 振 频 率:11.0592M
** 线路->单片机实验开发板B
******************************************************************/
;单片机内存分配申明!
A_BYTE EQU 20H ;数码管小数点后第1位数存放内存位置
B_BYTE EQU 21H ;数码管个位数存放内存位置
C_BYTE EQU 22H ;数码管十位数存放内存位置
TEMP_ADC EQU 23H ;用于保存AD结果(十进制)
ADC_CLK BIT P1.2;
ADC_DO BIT P1.3;
ADC_DI BIT P1.4;
ADC_CS BIT P1.7;
JDQ1 BIT P2.0 ;继电器1控制
JDQ2 BIT P2.1 ;继电器2控制
PS0 BIT P2.4 ;数码管小数点后第1位
PS1 BIT P2.5 ;数码管个位
PS2 BIT P2.6 ;数码管十位
PS3 BIT P2.7 ;数码管百位
;进行温度显示,这里我们考虑用网站提供的两位数码管来显示温度
;显示范围00到99度,显示精度为1度
;因为12位转化时每一位的精度为0.0625度,我们不要求显示小数,所以可以抛弃TEMPER_L的
;低4位,将TEMPER_H中的低4位移入TEMPER_L中的高4位,这样获得一个新字节,这个字节就是
;实际测量获得的温度这个转化温度的方法非常简洁无需乘于0.0625系数
ORG 0000H
SJMP MAIN
ORG 0030H
MAIN: MOV SP,#60H
MOV SCON,#50H ;设置成串口1方式
MOV TMOD,#20H ;波特率发生器T1工作在模式2上
MOV TH1,#0FAH ;预置初值(按照波特率4800BPS预置初值)
MOV TL1,#0FAH ;预置初值(按照波特率4800BPS预置初值)
;ORL PCON, #80H;波特率加倍
SETB TR1 ;启动定时器T1
LOOP: ACALL ADC;调用AD转换子程序
MOV R3,#0
MOV R4,A
MOV R7,#50 ;乘以50再除以255 得到实际电压值的10倍 这样就可以保留小数点后1位
ACALL NMUL21
MOV R7,#255
ACALL NDIV31
MOV TEMP_ADC,R4
MOV A,R3
MOV R2,A
MOV A,R4
MOV R3,A
ACALL HTD ;转换成十进制
MOV A,R6
ANL A,#0FH
MOV A_BYTE,A
MOV A,R6
SWAP A
ANL A,#0FH
MOV B_BYTE,A
MOV A,R5
ANL A,#0FH
MOV C_BYTE,A
ACALL SEND ;调用串口显示子程序
ACALL DISPLAY;调用数码管显示子程序
MOV A,R6 ;判断电压>45(4.5V)
CJNE A,#45H,LOOP2
SETB JDQ1
SETB JDQ2
SJMP LOOP
LOOP2: JC LOOP3
CLR JDQ1
SETB JDQ2
SJMP LOOP
LOOP3: SETB JDQ1
MOV A,R6 ;判断电压<5(0.5V)
CJNE A,#5H,LOOP4
SETB JDQ2
SJMP LOOP
LOOP4: JNC LOOP5
CLR JDQ2
SJMP LOOP
LOOP5: SETB JDQ2
SJMP LOOP
/******************************************************************
** 单片机与PC串口通信2
** 晶 振 频 率:11.0592M
** 线路->单片机实验开发板B
******************************************************************/
;单片机内存分配申明!
A_BYTE EQU 20H ;数码管小数点后第1位数存放内存位置
B_BYTE EQU 21H ;数码管个位数存放内存位置
C_BYTE EQU 22H ;数码管十位数存放内存位置
TEMP_ADC EQU 23H ;用于保存AD结果(十进制)
ADC_CLK BIT P1.2;
ADC_DO BIT P1.3;
ADC_DI BIT P1.4;
ADC_CS BIT P1.7;
JDQ1 BIT P2.0 ;继电器1控制
JDQ2 BIT P2.1 ;继电器2控制
PS0 BIT P2.4 ;数码管小数点后第1位
PS1 BIT P2.5 ;数码管个位
PS2 BIT P2.6 ;数码管十位
PS3 BIT P2.7 ;数码管百位
;进行温度显示,这里我们考虑用网站提供的两位数码管来显示温度
;显示范围00到99度,显示精度为1度
;因为12位转化时每一位的精度为0.0625度,我们不要求显示小数,所以可以抛弃TEMPER_L的
;低4位,将TEMPER_H中的低4位移入TEMPER_L中的高4位,这样获得一个新字节,这个字节就是
;实际测量获得的温度这个转化温度的方法非常简洁无需乘于0.0625系数
ORG 0000H
SJMP MAIN
ORG 0030H
MAIN: MOV SP,#60H
MOV SCON,#50H ;设置成串口1方式
MOV TMOD,#20H ;波特率发生器T1工作在模式2上
MOV TH1,#0FAH ;预置初值(按照波特率4800BPS预置初值)
MOV TL1,#0FAH ;预置初值(按照波特率4800BPS预置初值)
;ORL PCON, #80H;波特率加倍
SETB TR1 ;启动定时器T1
LOOP: ACALL ADC;调用AD转换子程序
MOV R3,#0
MOV R4,A
MOV R7,#50 ;乘以50再除以255 得到实际电压值的10倍 这样就可以保留小数点后1位
ACALL NMUL21
MOV R7,#255
ACALL NDIV31
MOV TEMP_ADC,R4
MOV A,R3
MOV R2,A
MOV A,R4
MOV R3,A
ACALL HTD ;转换成十进制
MOV A,R6
ANL A,#0FH
MOV A_BYTE,A
MOV A,R6
SWAP A
ANL A,#0FH
MOV B_BYTE,A
MOV A,R5
ANL A,#0FH
MOV C_BYTE,A
ACALL SEND ;调用串口显示子程序
ACALL DISPLAY;调用数码管显示子程序
MOV A,R6 ;判断电压>45(4.5V)
CJNE A,#45H,LOOP2
SETB JDQ1
SETB JDQ2
SJMP LOOP
LOOP2: JC LOOP3
CLR JDQ1
SETB JDQ2
SJMP LOOP
LOOP3: SETB JDQ1
MOV A,R6 ;判断电压<5(0.5V)
CJNE A,#5H,LOOP4
SETB JDQ2
SJMP LOOP
LOOP4: JNC LOOP5
CLR JDQ2
SJMP LOOP
LOOP5: SETB JDQ2
SJMP LOOP
;(8位串行A/D芯片兼容ADC0832)
;=================================
;AD转换子程序
;=================================
ADC: SETB ADC_DI
SETB ADC_DO
SETB ADC_CLK
CLR ADC_CS
NOP
SETB ADC_CS ;
CLR ADC_CLK
CLR ADC_CS ;开始采集
CALL D1MS ;延时子程序
SETB ADC_DI ;首个位为1(起始位)
SETB ADC_CLK ;时钟上升沿
NOP
CLR ADC_CLK ;
SETB ADC_DI ;又一个时钟上升沿用于极性选择.
SETB ADC_CLK ;SGL=1 (单极性对地)而不是对VREF
NOP
CLR ADC_CLK
CLR C ;0地址选择位单元
MOV ADC_DI,C
SETB ADC_CLK ;又一个时钟上升沿用于选地址
NOP
CLR ADC_CLK
NOP
SETB ADC_CLK ;第四个时钟上升沿
NOP
CLR ADC_CLK
NOP
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK ;时钟下降沿读入数据
RLC A ;7
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;6
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;5
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;4
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;3
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;2
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;1
SETB ADC_CLK
MOV C,ADC_DO
CLR ADC_CLK
RLC A
;0
SETB ADC_CLK
NOP
CLR ADC_CLK ;1
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;2
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;3
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;4
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;5
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;6
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;7
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;wait for 高阻态
NOP
SETB ADC_CLK
NOP
CLR ADC_CLK ;wait for 高阻态
NOP
CALL D1MS
SETB ADC_CS
RET
;----------------------
;串口发送数据子程序
;----------------------
SEND: CLR TI
MOV SBUF,TEMP_ADC
JNB TI,$
RET
DISPLAY: MOV DPTR,#NUMTAB ;指定查表启始地址
MOV R0,#4
DPL1: MOV R1,#250 ;显示1000次
DPLOP: mov a,A_BYTE ;取小数点后第1位数
MOVC A,@A+DPTR ;查个位数的7段代码
mov p0,a ;送出个位的7段代码
CLR PS0
SETB PS1
SETB PS2
SETB PS3
acall d1ms ;显示1ms
mov a,B_BYTE ;取个位数
MOVC A,@A+DPTR ;查十位数的7段代码
ORL A,#01H
mov p0,a ;送出十位的7段代码
SETB PS0
CLR PS1
acall d1ms ;显示1ms
mov a,C_BYTE ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
mov p0,a ;送出十位的7段代码
SETB PS1
CLR PS2
acall d1ms ;显示1ms
SETB PS2
djnz r1,dplop ;100次没完循环
djnz r0,dpl1 ;4个100次没完循环
ret
;单字节无符号数乘法程序 (R3R4*R7)=(R2R3R4)
;入口: R3,R4,R7
;占用资源: ACC,B
;堆栈需求: 2字节
;出口: R2,R3,R4
NMUL21 : MOV A,R4
MOV B,R7
MUL AB
MOV R4,A
MOV A,B
XCH A,R3
MOV B,R7
MUL AB
ADD A,R3
MOV R3,A
CLR A
ADDC A,B
MOV R2,A
CLR OV
RET
;单字节无符号除法程序 (R2R3R4/R7)=(R2)R3R4 余数R7
;入口: R2,R3,R4,R7
;占用资源: ACC,B,F0
;堆栈需求: 3字节
;出口: (R2),R3,R4,R7,OV
NDIV31 : MOV A,R2
MOV B,R7
DIV AB
PUSH ACC
MOV R2,B
MOV B,#10H
NDV311 : CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
MOV F0,C
CLR C
SUBB A,R7
JB F0,NDV312
JC NDV313
NDV312 : MOV R2,A
INC R4
NDV313 : DJNZ B,NDV311
POP ACC
CLR OV
JZ NDV314
SETB OV
NDV314 : XCH A,R2
MOV R7,A
RET
HTD: CLR A ;R2和R3是程序数据入口
MOV R4,A ;转换后的数放在R4,R5,R6
MOV R5,A ;转换完后在分别屏蔽高位和低位取出数据
MOV R6,A
MOV R7,#10H
ZH: CLR C
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
MOV A,R6
ADDC A,R6
DA A
MOV R6,A
MOV A,R5
ADDC A,R5
DA A
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
DJNZ R7,ZH
RET
D1MS: MOV R7,#80 ;1MS延时
DJNZ R7,$
RET
numtab: DB 0FCH,60H,0DAH,0F2H,66H,0B6H,0BEH,0E0H,0FEH,0F6H ;实验板上的7段数码管0~9数字的共阴显示代码
END
keil工程文件打包下载 asm.rar
上一篇:单片机与PC串口通信1