OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4394|回复: 11

基于51单片机的直流数字电压表(0-5V)

[复制链接]

6

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2016-4-2
在线时间
33 小时
发表于 2016-4-27 01:15:54 | 显示全部楼层 |阅读模式


利用串行A/D转换器TLC549对输入信号电压源进行采集转换成数字信号给51单片机,经单片机进行数据处理后给1602液晶显示。
误差小于1%.
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar LCD[6];   //电压数据转换成LCD1602液晶字符显示
uint Volt;
sbit DO  = P1^0;        //时钟
sbit CS  = P1^1;        //片选
sbit CLK = P1^2;        //数据输出
sbit RS = P2^0;                        //1602液晶数据/命令选择端
sbit RW = P2^1;                        //1602液晶读写端
sbit E  = P2^2;                        //1602液晶使能端

// Function Prototypes
void check_busy(void);
void write_command(uchar com);
void write_date(uchar date);
void LCD_init(void);
void string(uchar ad ,uchar *s);
//void lcd_test(void);
void delay(uint);
void Volt_To_LCD1602(void);
void delay_ms(uint xms);
void Data_Conversion(void);
uchar TLC549_ADC(void);
/*******************************************
    LCD1602 Driver mapped as IO peripheral
*******************************************/  
// Delay
// Delay
void delay(uint j)
{
        uchar i = 60;
  for(; j>0; j--)
  {
                while(--i);
    i = 59;
    while(--i);
    i = 60;
  }
}

// Test the Busy bit
void check_busy(void)
{
        do
  {
                P0 = 0xff;
    E = 0;
    RS = 0;
    RW = 1;
    E = 1;
    _nop_();
  } while(P0 & 0x80);
  E = 0;
}

// Write a command
void write_command(uchar com)
{
        check_busy();
  E = 0;
  RS = 0;
  RW = 0;
  P0 = com;
  E = 1;
  _nop_();
  E = 0;
  delay(1);
}

// Write Data
void write_date(uchar date)
{
        check_busy();
  E = 0;
  RS = 1;
  RW = 0;
  P0 = date;
  E = 1;
  _nop_();
  E = 0;
  delay(1);   
}

// Initialize LCD controller
void LCD_init(void)
{
        write_command(0x38); // 8-bits, 2 lines, 7x5 dots
  write_command(0x0C); // no cursor, no blink, enable display
  write_command(0x06); // auto-increment on
  write_command(0x01); // clear screen
  delay(1);
}

// Display a string
void string(uchar ad, uchar *s)
{
        write_command(ad);
  while(*s>0)
  {
                 write_date(*s++);
     delay(100);
  }
}
//****************************************************//
//函数名:delay_ms(uint xms)
//函数功能:ms级延时函数
//***************************************************//

void delay_ms(uint xms)
{
        uint x,y;
        for(x=xms;x>0;x--)
                for(y=110;y>0;y--);
        
}

//***************************************************//
//函数名称:TLC549_ADC()
//函数功能:读取上一次A/D转换的数据,启动下一次A/D转换
//**************************************************//
uchar TLC549_ADC(void)
{
        uchar n, tmp;

        CS  = 1;                     //CS置高,片选无效
        CLK = 0;

        CS  = 0;                     //CS置低,片选有效,同时DO输出高位
        _nop_();
        _nop_();                     //适当延迟时间1.4us Setup Time

        for(n = 0; n < 8; n++) //串行数据移位输入
        {
                tmp <<= 1;
                tmp |=  DO;

                CLK = 1;        //0.4us
                _nop_();          //CLK transition time Max 0.1us
                CLK = 0;        //0.4us
        }
        CS = 1;            //CS置高,片选无效
        for(n = 17; n != 0; n--) _nop_();  //Next Coversion需要延迟17us
        return (tmp);
}
//****************************************//
//函数名称ata_Conversion()
//函数功能:电压换算
//*****************************************//
void Data_Conversion(void)
{
        uchar AD_Data;

        AD_Data = TLC549_ADC();
        delay_ms(1000);
        Volt = 5.0 / 256 * AD_Data*1000;
}

void Volt_To_LCD1602(void)
{
        Data_Conversion();                     //电压换算并放大1000倍
        LCD[0] = Volt/1000;         //千位
        LCD[1] = '.';                                //小数点
        LCD[2] = Volt/100%10;  //百位
        LCD[3] = Volt/10%10;    //十位
        LCD[4] = Volt%10;           //个位
        LCD[5] = 'V';                              //字符V

        write_command(0x80+8);
        write_date(0x30+LCD[0]);
        write_date(LCD[1]);
        write_date(0x30+LCD[2]);
        write_date(0x30+LCD[3]);
        write_date(0x30+LCD[4]);
        write_date(LCD[5]);

}
        
int main()
{
        //uint m;
        LCD_init();
        
  delay(100);
  write_command(0x01);
        write_command(0x80);
        string(0x80,"Voltage:");
        delay_ms(2000);



        while(1)
        {
                Volt_To_LCD1602();
               
        }
        
}
QQ截图20160427010522.png
QQ截图20160427010543.png

串行AD转换电路仿真.zip

71.36 KB, 下载次数: 589

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

39

主题

598

帖子

0

精华

高级会员

Rank: 4

积分
875
金钱
875
注册时间
2013-12-18
在线时间
41 小时
发表于 2016-4-27 08:07:03 | 显示全部楼层
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-4-27 11:55:46 | 显示全部楼层
谢谢分享.....
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

25

主题

157

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2013-11-24
在线时间
5 小时
发表于 2016-4-27 12:01:15 | 显示全部楼层
效果怎样?几位AD?
回复 支持 反对

使用道具 举报

6

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2016-4-2
在线时间
33 小时
 楼主| 发表于 2016-4-27 19:15:47 | 显示全部楼层
noname 发表于 2016-4-27 12:01
效果怎样?几位AD?

8位AD,0-5V电压测量误差很小,小于0.1%
回复 支持 反对

使用道具 举报

7

主题

266

帖子

0

精华

高级会员

Rank: 4

积分
671
金钱
671
注册时间
2014-7-6
在线时间
105 小时
发表于 2016-4-27 21:54:27 | 显示全部楼层
8位做不到0.1%,8位的分辨率才0.4%
回复 支持 反对

使用道具 举报

6

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2016-4-2
在线时间
33 小时
 楼主| 发表于 2016-4-27 23:48:46 | 显示全部楼层
木瓜 发表于 2016-4-27 21:54
8位做不到0.1%,8位的分辨率才0.4%

之前说错了,8位最大也只能做到大于0.4%,我这个反正小于1%没问题,你可以下载我上传的附件下来仿真下,看有什么问题没
回复 支持 反对

使用道具 举报

7

主题

266

帖子

0

精华

高级会员

Rank: 4

积分
671
金钱
671
注册时间
2014-7-6
在线时间
105 小时
发表于 2016-4-28 08:32:49 | 显示全部楼层
叶致习 发表于 2016-4-27 23:48
之前说错了,8位最大也只能做到大于0.4%,我这个反正小于1%没问题,你可以下载我上传的附件下来仿真下,看 ...

我没有那个软件,玩不起来
回复 支持 反对

使用道具 举报

6

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2016-4-2
在线时间
33 小时
 楼主| 发表于 2016-4-28 08:39:57 | 显示全部楼层
木瓜 发表于 2016-4-28 08:32
我没有那个软件,玩不起来

哦哦,有带TLC549的A/D转换器的开发板就能实物调试了
回复 支持 反对

使用道具 举报

7

主题

266

帖子

0

精华

高级会员

Rank: 4

积分
671
金钱
671
注册时间
2014-7-6
在线时间
105 小时
发表于 2016-4-28 09:08:47 | 显示全部楼层
叶致习 发表于 2016-4-28 08:39
哦哦,有带TLC549的A/D转换器的开发板就能实物调试了

我都玩16位,24位的,工作中都极少用8位了
回复 支持 反对

使用道具 举报

6

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2016-4-2
在线时间
33 小时
 楼主| 发表于 2016-4-29 02:07:09 | 显示全部楼层
木瓜 发表于 2016-4-28 09:08
我都玩16位,24位的,工作中都极少用8位了

哦哦,确实如果是在工作最好还是要用16位和24位的,我发现网上16位和24位A/D的中文资料很少耶,不知道是因为要在实际项目中运用,大家都不会分享出来?不像ADC0832,ADC0809,TLC549这些老版的8位A/D没什么太大实际项目应用价值,也适合初学者所以资料就多吗
回复 支持 反对

使用道具 举报

7

主题

266

帖子

0

精华

高级会员

Rank: 4

积分
671
金钱
671
注册时间
2014-7-6
在线时间
105 小时
发表于 2016-4-29 10:48:29 | 显示全部楼层
叶致习 发表于 2016-4-29 02:07
哦哦,确实如果是在工作最好还是要用16位和24位的,我发现网上16位和24位A/D的中文资料很少耶,不知道是 ...

资料应该还是比较多的,实际项目应用的,工程师当然不会那么容易就分享出来,其实有点点基础,ADI很多的ADC都有中文资料,操作一个ADC是很简单的事情,祝你天天向上
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 16:44

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表