1)原理图我博客上有
(2)程序清单:
名称:数字电压表
作者w418781840,日期:2008.6.12
功能:实验现0~~5V电压的测量,测量值用三位数管显示
CLK BIT P3.5定义CLK
ORG 0000H
LJMP MAIN 转入主程序
ORG 0013H
LJMP AGA 中断TNT1,用于读取转换后的数据
ORG 001BH
LJMP WQ T1中断入口,用于产生时钟和显示
主程序
ORG 0030H
MAIN: MOV TMOD,#10H 工作方式1
MOV TH1,#(65536-200)/256 产生500HZ
MOV TL1,#(65536-200)%256
SETB EA 开总中断.
SETB ET1 开T1中断
SETB TR1 启动T1
SETB EX1 开外部中断1
SETB IT1 边沿触发
MOV DPTR ,#1FFFH 指向通道INC0
MOVX @DPTR,A 启动转换
LOOP: LCALL DISPLAY 调用显示程序.
SJMP LOOP
外部1中断,;显示数据转为3位BCD码子程序
;显示数据转为3位BCD码存入33H,34H,35H(最大值约为5.00V)
AGA: MOV DPTR,#1FFFH
MOVX A,@DPTR 读取转换后的数据.
MOV B,#51 255÷51=5.00V运算
DIV AB
MOV 33H,A ;个位数放入33H
MOV A,B ;余数大于19H,F0为1,乘法溢出,结果加5
CLR F0
SUBB A,#1AH
MOV F0,C
MOV A,#10
MUL AB
MOV B,#51
DIV AB
JB F0,LOOP2
ADD A,#5
LOOP2: MOV 34H,A ;小数后第一位放入34H
MOV A,B
CLR F0
SUBB A,#1AH
MOV F0,C
MOV A,#10
MUL AB
MOV B,#51
DIV AB
JB F0,LOOP3
ADD A,#5H
LOOP3: MOV 35H,A ;小数后第二位放入35H
MOVX @DPTR,A 启动转换
RETI
显示程序
DISPLAY: MOV R1,#33H 指向显示数据首址
MOV R0,#0FEH 扫描控制字初值
PLAY: MOV A,R0 扫描字放入A
MOV P2,A 从P2口输出
MOV A,@R1 取显示数据到A
MOV DPTR,#TAB 取段码表地址
MOVC A,@A+DPTR 查显示数据对应段码
CJNE R0,#0FEH,PAP 查看是第一位否.
ORL A,#80H 是,则取小数点.
PAP: MOV P1,#0FFH 防闪烁.
MOV P1,A 段码放入P1口
LCALL DL1MS 显示1MS
INC R1 指向下一地址
MOV A,R0 扫描控制字放入A
JNB ACC.2,ENDOUT ACC.3=0时一次显示结束
RL A A中数据循环左移
MOV R0,A 放回R5内
AJMP PLAY 跳回PLAY循环
ENDOUT: RET
TAB: DB 3fH,06H,5bH,4fH,66H,6dH,7dH,07H,7fH,6fH
延时程序
1MS延时程序,LED显示程序用
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
T1定时器中断服务程序,用于给ADC0809产生时钟周期
WQ: MOV TH1,#(65536-200)/256
MOV TL1,#(65536-200)%256
CPL CLK 取反.
RE: RETI
END
在做油量检测模拟时写的小程序 希望对你有用~~~程序用到的lcd.h 实在不会写的话或是看不懂的话再找我吧~
#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define sound_port PD7 //报警端口
#define warm_charge PD6 //红灯亮,加油
#define warm_discharge PD5 //绿灯亮,正常
#define botton_port PORTD
#define botton_pin PIND //按键端口,PD 低四位
#include"lcd160204.h" //LCD 4线驱动
#include"lcd.h"//数据类型转换成字符串输出
//全局变量
float v,now_adc,warm_line=2.12,get_average,adc_val,get_val[20]
float adc_convert(void) //ADC转换值读取
{
int temp1,temp2
float temp
temp1=ADCL //必须先读低位
temp2=ADCH
temp2=(temp2<<8)+temp1
temp=(float)temp2
return(temp)
}
//20 次采样,求取平均值
float find_effectval(float *array)
{
uchar i
float min_val,max_val,sum,average
min_val=array[0]
max_val=array[0]
for(i=1i<20i++)
if(min_val>array[i]) min_val=array[i]
for(i=1i<20i++)
if(max_val<array[i]) max_val=array[i]
for(i=0i<20i++)
sum+=array[i]
average = (sum - min_val - max_val)/18.0
return(average)
}
void sound(void)//警报声 100ms
{
uint a
for(a=0a<10a++)
{
PORTD|=BIT(sound_port)
delay_1ms()
PORTD&=~BIT(sound_port)
delay_1ms()
}
}
//报警检测
void warm(void)
{
if(v<warm_line) //红灯
{
PORTD&=~BIT(warm_charge)
PORTD|=BIT(warm_discharge)
sound()
}
else //绿灯
{
PORTD&=~BIT(warm_discharge)
PORTD|=BIT(warm_charge)
//sound()
}
}
//报警值修改函数,做按键扫描
void change_warm(void)
{
delay_nms(30)
if((botton_pin&0x0f)!=0x0f)
{
delay_nms(50)
switch(botton_pin&0x0f)
{
case 0x0e: warm_line += 0.02break
case 0x0d: warm_line += 0.2break
case 0x0b: warm_line -= 0.02break
case 0x07: warm_line -= 0.2break
default :break
}
}
}
void show(void)
{
locate(1,1)
lcd_str("adc:")
locate(1,5)
lcd_long_to_char(get_average)
lcd_str("")
locate(1,8)
lcd_str("val:")
locate(1,12)
lcd_float_to_char(v)
lcd_str("")
locate(2,1)
lcd_str("warm_line :")
locate(2,12)
lcd_float_to_char(warm_line)
lcd_str(" ")
}
void init_all(void)
{
DDRA = 0xfe //设置A口 不带上拉输入;
PORTA = 0x00
DDRD = 0xe0
PORTD = 0x7f
lcd_init()
cls()
//延时待系统稳定;
delay_nms(200)
locate(1,2)
lcd_str("loading system!")
locate(2,2)
lcd_str("please wait!")
delay_nms(2000)
cls()/**/
}
void get_adc_info(void)
{
uchar x
for(x=0x<20x++)
{
ADMUX=0x40
ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIF)//AD转换使能,启动ADC转换 ,二分频
while(!(ADCSRA&(1<<ADIF)))//等待AD转换结束
adc_val=adc_convert()
get_val[x]=adc_val
delay_nms(30)
change_warm() //报警值修改
}
get_average = find_effectval(get_val)
v = (get_average*5.0)/(1023*1.0)
}
void main(void)
{
//float adc_val,get_val[20],get_average
init_all()
while(1)
{
get_adc_info() //获取信息并做处理
warm() //报警检测
show() //显示信息
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)