|
这个程序也是在本论坛上找的,在使用ADC0832模块读取电压值时,发现转换的电压值同电压表显示的有偏差,现在想通过修正使两者基本一致,即不同的电压范围加上相应的数字,条件如下:
1.AD值在0.2以下时不加;
2.大于0.2,小于1.0时加0.05;
3.大于1.0,小于3.0时加0.1
4.大于3.0,小于4.0时加0.13
5.大于4.0时,加0.16
还有一个需求:
电压值在0.2以下或1.5-3.0范围时点亮P3.0,其它的值均点亮P3.1。
感谢各位老师。
以下是目前使用的单片机程序:
- //-----------------------------------------------------------------
- // 说明: 调整VR1时,ADC0832将模拟电压转换为数字电压显示在1602液晶
- // 屏第0行,液晶屏第1行同时以进程条方式显示当前电压大小.
- //
- //-----------------------------------------------------------------
- #include <reg51.h>
- #include <intrins.h>
- #include <string.h>
- #define uchar unsigned char
- #define uint unsigned int
- //ADC0832引脚定义
- sbit CS = P1^0; //片选线(电路中固定连接低电平)
- sbit CLK = P1^1; //时钟线
- sbit DIO = P1^2; //数据线
- //LCD1602端口定义
- sbit RS = P2^5; //寄存器选择
- sbit RW = P2^6; //读写控制
- sbit E = P2^7; //使能控制
- #define LCD_PORT P0 //液晶端口
- uchar Disp_Buff1[] = " VOLTAGE: 0.00V"; //数字电压显示缓冲
- uchar Disp_Buff2[16]; //进程条图形显示缓冲
- #define delay4us() { _nop_();_nop_();_nop_();_nop_();}
- //-----------------------------------------------------------------
- // 延时函数
- //-----------------------------------------------------------------
- void delay_ms(uint x)
- {
- uchar t; while(x--) for(t = 0; t < 120; t++);
- }
- //-----------------------------------------------------------------
- // 读LCD忙状态
- //-----------------------------------------------------------------
- bit Read_LCD_Busy_Flag()
- {
- uchar result;
- LCD_PORT=0xff; //液晶屏端口电平拉高
- RS=0;RW=1; //选择命令寄存器,准备读
- E=1;delay4us(); result=P0; E=0; //下降沿读命令寄存器
- return (result&0x80)? 1 : 0; //返回忙状态
- }
- //-----------------------------------------------------------------
- // 写LCD命令
- //-----------------------------------------------------------------
- void Write_LCD_Command(uchar cmd)
- {
- while(Read_LCD_Busy_Flag()); //液晶屏忙等待
- RS=0;RW=0; //选择命令寄存器,准备写
- E=0; _nop_();_nop_();LCD_PORT=cmd; //数据送到液晶屏端口
- delay4us();E=1;delay4us();E=0; //写入后禁止液晶屏
- }
- //-----------------------------------------------------------------
- // 写LCD数据
- //-----------------------------------------------------------------
- void Write_LCD_Data(uchar dat)
- {
- while(Read_LCD_Busy_Flag()); //液晶屏忙等待
- RS=1;RW=0; //选择数据寄存器,准备写
- E=0; LCD_PORT=dat; delay4us(); //数据送到液晶屏端口
- E=1;delay4us(); E=0; //写入后禁止液晶屏
- }
- //-----------------------------------------------------------------
- // 在LCD指定行/列位置显示字符串
- //-----------------------------------------------------------------
- void LCD_Show_String(uchar r,uchar c, char *s)
- {
- uchar i=0;
- uchar code DDRAM[]={0x80,0xc0}; //液晶屏上下两行的DDRAM首地址
- Write_LCD_Command(DDRAM[r] | c); //设置显示起始位置
- while(s[i] && i<16) Write_LCD_Data(s[i++]); //输出显示字符
- }
- //-----------------------------------------------------------------
- // LCD初始化
- //-----------------------------------------------------------------
- void LCD_Initialise()
- {
- Write_LCD_Command(0x38); delay_ms(1);
- Write_LCD_Command(0x0C); delay_ms(1);
- Write_LCD_Command(0x06); delay_ms(1);
- Write_LCD_Command(0x01); delay_ms(1);
- }
- //-----------------------------------------------------------------
- // 获取AD转换结果 ( 0通道 )
- //-----------------------------------------------------------------
- uchar Get_AD_Result()
- {
- uchar i,dat1=0,dat2=0;
- //使能ADC0832,时钟线初始置低电平
- CS=0; CLK=0;
- //第1个时钟脉冲上升沿之前,通过DIO选择模式
- DIO=1; _nop_();_nop_();
- CLK=1; _nop_();_nop_();
- //第2个时钟脉冲上升沿之前,通过DIO选择模式
- //设DI=1选择单端(SGL) 设DI=0 选择分差(DIF)
- //下面设置的是单端模式
- CLK=0; DIO=1; _nop_();_nop_();
- CLK=1; _nop_();_nop_();
- //第2个时钟脉冲上升沿之前,设DI=0/1,分别对应选择CH0/CH1
- CLK=0; DIO=0; _nop_();_nop_();
- CLK=1; _nop_();_nop_();
- //第3个时钟脉冲下升沿之后置DI=1,释放数据线,准备接收(设置原理可参考第一章端口说明)
- //P1端口读取数据时需要先写1,否则总线将出现逻辑冲突(黄色方块闪烁)
- CLK=0; DIO=1; _nop_();_nop_();
- //根据时序图可知,在正式读取转换数据之前,此时的D0将固定输出0
- //P3=(uchar)DIO;
- //第4~11,共8个下降沿读数据(MSB-LSB)
- for(i=0;i<8;i++)
- {
- CLK=1; _nop_();_nop_();
- CLK=0; _nop_();_nop_();
- dat1<<=1;
- if(DIO)
- dat1=dat1+0x01;
- }
- //第11~18,共8个下降沿读数据(LSB——MSB)
- for(i=0;i<8;i++)
- {
- dat2>>=1;
- if(DIO)
- dat2=dat2+0x80;
- CLK=1; _nop_();_nop_();
- CLK=0; _nop_();_nop_();
- }
- CS=1; //禁止ADC0832
- //如果MSB——LSB和LSB——MSB读取的结果相同则返回读取的结果,否则返回0
- if(dat1==dat2)
- return dat1;
- return 0x00;
- }
- //-----------------------------------------------------------------
- // 主程序
- //-----------------------------------------------------------------
- void main()
- {
- uchar AD; uint d; //注意d的类型为uint
- LCD_Initialise(); //初始化LCD
- while(1)
- {
- AD=Get_AD_Result(); //获取A/D转换值
- //根据四舍五入法计算电压值(放大100倍以便分解)
- d=AD*500.0*2/511.0;
- //根据舍尾取整数计算电压值(放大100倍以便分解)
- //将d = AD*500.0/256;
- //将AD转换后得到数据分解为三个数位
- Disp_Buff1[11] = d / 100 +'0';
- Disp_Buff1[13] = d / 10 %10 +'0';
- Disp_Buff1[14] = d % 10 +'0';
- LCD_Show_String(0,0,Disp_Buff1);
- //将模数值折算为实心方块及空心方框字符个数,控制进程条图形显示
- }
- }
复制代码 |
|