51单片机 ADC0832酒精传感器

ADC0832

环境:

软件:

  • uVision
  • proteus

芯片

  • 80c51
  • ADC0832、LCD1602

仿真图

在这里插入图片描述

相关函数编写电平时

代码

1602

头文件
#include<reg51.h>
#include<intrins.h> //使用_nop_();
#include<string.h>
宏定义
// RS为寄存器选择,高电平时选择寄存器,低电平时选择指令寄存器
sbit RS = P2^0;
// RW为读写信号线,高电平时进行读操作,低电平时进行写操作 
sbit RW = P2^1;
// EN为使能端,当EN端由高电平跳变成低电平时,液晶模块执行命令
sbit EN = P2^2;
初始化
/**
* LCD初始化
*
* @return
*/
void init()
{
	/*
	  0011_1000 置功能
 	  DL=1 --> 8位总线
	  N=0  --> 单行显示
	  F=0  -->	显示5x7的点阵字符
	*/	
	write_cmd(0x38);
	
	/*
	  0000_0001 清显示
	  指令码01H,光标复位到地址00H位置
	*/ 
	write_cmd(0x01);
	
	/*
	  0000_0110 置输入模式
	  I/D=1 --> 光标右移
	  S=0   --> 屏幕上所有文字左移或右移
	*/
	write_cmd(0x06);
	
	/*
	  0000_1100	显示开/关控制
	  D=1 --> 开显示
	  C=0 --> 无光标
	  B=0 --> 光标不闪烁
	*/
	write_cmd(0x0C);
}
检测BF(busy flag)位状态
/*
* 检测BF(busy flag)位状态
*  防止不能识别,需用延时函数代替
* @return
*/
void test_BF()
{
	unsigned char LCD_status;
	do{
		P0 = 0xFF; // LCD1602读取状态数据,必须有一个上拉电平
		EN = 0; RS = 0; RW = 1; // RS为0时,P0的数据为命令
		EN=1;// 让RS和RW设置有效
		LCD_status = P0;
		_nop_(); _nop_();
		EN = 0;
	}while(LCD_status&0x80); // 1000_0000 忙碌状态
}
写数据
/*
* 写数据(一位一位的写)
*
* @param data8 八位数据
* @return
*/
void write_data(unsigned char data8)
{
	test_BF();
	EN = 0; RS = 1; RW = 0;
	P0 = data8;
	EN = 1; _nop_(); EN = 0;
}
写命令
/*
* 写命令
*
* @param cmd8 八位命令
* @return
*/
void write_cmd(unsigned char cmd8)
{
	test_BF();
	EN = 0; RS = 0; RW = 0;
	P0 = cmd8;
	EN = 1; _nop_(); EN = 0;
}
写字符串
/**
* 写字符串
*
* @param r row 0---第一行  1---第二行
* @param c column
* @param str 字符串
* @return
*/
void write_str(int r, int c, char *str)
{
	int i=0;	
	unsigned char Addressx[] = {0x80, 0xC0};
	unsigned char StartAdd = (Addressx[r] | c);//按位或

	write_cmd(StartAdd);
	
	for(i = 0; i < 16; i++){
		if(str[i]==0) break;
		write_data(str[i]);
	}
	// 如果不够16位,用空格填充
	for(;i < 16; i++){
		write_data(' '); 	
	}
}

0832

头文件
//ADC0832 
sbit CS = P3^2;
sbit CLK = P3^3;
sbit DIDO = P3^4;
转换方法
//------------------------------
//     获取AD转换结果(0通道)
//------------------------------
uchar Get_AD_Result()         //包含11个CLK下降沿      
{
    uchar i, dat;
    CS = 1;              //ADC0832未工作时,CS端为高电平,此时芯片禁用
    _nop_;               //对于延时很短的,要求在us级的,采用“_nop_”函数      
    CLK =1;                  
    CS = 0;
    DIDO = 1; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第一个下降沿来到时,DI = 1启动ADC0832
    DIDO = 1; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第二个下降沿 
    DIDO = 0; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第三个下降沿,发送1,0选择通道cho
    DIDO = 1;                                //释放总线
    for(i = 0; i < 8; i++)                  //第4个下降沿到第11个下降沿
    {
        CLK = 0;                           //clk处于下降沿,每一个下降沿DO端输入下一个
        _nop_;                              //对于延时很短的,要求在us级的,采用_nop_函数      
        if(DIDO) dat |= 0x01;              // dat = dat | 0x01,dat和0x01做“或”的运算,意思是最低位置1,其它位保持不变。
        CLK = 1; _nop_;                      //clk处于上升沿
        dat <<= 1;                          //数据左移
    }
    return (dat);
    CS = 1;                                  //ADC0832停止工作
}

主函数编写

头文件
#include <reg52.h>
#include <1602.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
宏定义
//ADC0832 
sbit CS = P3^2;
sbit CLK = P3^3;
sbit DIDO = P3^4;

LCD1602.h

#include <reg52.h>
#define LCD1602_DB P2
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^2;
void InitLcd1602();
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

/*
void delay(unsigned int i)
{
	while(i--);	
}
*/
void LcdStar()
{
	unsigned char str[] = "Voltage measure";
	unsigned char tab[]="Voltage= "; 
	InitLcd1602();/* 初始化 1602 液晶 */
	LcdShowStr(1, 0, str);
	LcdShowStr(1, 1, tab);
	LcdShowStr(9, 1, "...");//默认初始化温度00
	LcdShowStr(13, 1, "V");//添加V电压
}

void delay(int z){
	int x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}

/* 等待液晶准备好 */
void LcdWaitReady()
{
    /*
    * 检测BF(busy flag)位状态
    *  防止不能识别,需用延时函数代替
    * @return
    */
	unsigned char LCD_status;
	do{
		LCD1602_DB = 0xFF; // LCD1602读取状态数据,必须有一个上拉电平
		LCD1602_E = 0; LCD1602_RS = 0; LCD1602_RW = 1; // RS为0时,P0的数据为命令
		LCD1602_E=1;// 让RS和RW设置有效
		LCD_status = LCD1602_DB;
		_nop_(); _nop_();
		LCD1602_E = 0;
	}while(LCD_status&0x80); // 1000_0000 忙碌状态
	//delay(10);
}
/* 向 LCD1602 液晶写入一字节命令, cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
	LcdWaitReady();
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = cmd;
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/* 向 LCD1602 液晶写入一字节数据, dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
	LcdWaitReady();
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_DB = dat;
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/* 设置显示 RAM 起始地址,亦即光标位置, (x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
	unsigned char addr;
	if (y == 0) //由输入的屏幕坐标计算显示 RAM 的地址
		addr = 0x00 + x; //第一行字符地址从 0x00 起始
	else
		addr = 0x40 + x; //第二行字符地址从 0x40 起始
	LcdWriteCmd(addr | 0x80); //设置 RAM 地址
}
/* 在液晶上显示字符串, (x,y)-对应屏幕上的起始坐标, str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
	LcdSetCursor(x, y); //设置起始地址
	while (*str != '\0') //连续写入字符串数据,直到检测到结束符
	{
		LcdWriteDat(*str++); //先取 str 指向的数据,然后 str 自加 1
	}
}
/* 初始化 1602 液晶 */
void InitLcd1602()
{
	LcdWriteCmd(0x38); //16*2 显示, 5*7 点阵, 8 位数据接口
	LcdWriteCmd(0x0C); //显示器开,光标关闭
	LcdWriteCmd(0x06); //文字不动,地址自动+1
	LcdWriteCmd(0x01); //清屏
}

Main_0832.c

#include <reg52.h>
#include <1602.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
//ADC0832 
sbit CS = P3^2;
sbit CLK = P3^3;
sbit DIDO = P3^4;

uchar len;
//一位小数,电压显示
uchar Display_Buffer[4];

uchar Get_AD_Result();   //模数转换结果

//延时
void DelayMS(uint ms)
{
	uchar t;
	while(ms--)
	{
		for(t=0;t<120;t++);
	}
}

//------------------------------
//     获取AD转换结果(0通道)
//------------------------------
uchar Get_AD_Result()         //包含11个CLK下降沿      
{
    uchar i, dat;
    CS = 1;              //ADC0832未工作时,CS端为高电平,此时芯片禁用
    _nop_;               //对于延时很短的,要求在us级的,采用“_nop_”函数      
    CLK =1;                  
    CS = 0;
    DIDO = 1; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第一个下降沿来到时,DI = 1启动ADC0832
    DIDO = 1; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第二个下降沿 
    DIDO = 0; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第三个下降沿,发送1,0选择通道cho
    DIDO = 1;                                //释放总线
    for(i = 0; i < 8; i++)                  //第4个下降沿到第11个下降沿
    {
        CLK = 0;                           //clk处于下降沿,每一个下降沿DO端输入下一个
        _nop_;                              //对于延时很短的,要求在us级的,采用_nop_函数      
        if(DIDO) dat |= 0x01;              // dat = dat | 0x01,dat和0x01做“或”的运算,意思是最低位置1,其它位保持不变。
        CLK = 1; _nop_;                      //clk处于上升沿
        dat <<= 1;                          //数据左移
    }
    return (dat);
    CS = 1;                                  //ADC0832停止工作
}

void main()
{
	uint Data;
	InitLcd1602(); //LCD初始化
	LcdStar();
	DelayMS(10);
	while(1)
	{
		//获取AD转换值 最大值255对应最高电压5.00V
		//显示三个数 使用500
		Data = Get_AD_Result()*500.0/256;
		// 数据分解
		Display_Buffer[0]= Data /100+'0'; 
		Display_Buffer[1] = '.';
		Display_Buffer[2] = Data /10%10+'0';
		Display_Buffer[3] = Data %10+'0';
		LcdShowStr(9, 1,Display_Buffer);
	}
}
  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洛尘~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值