ADC0809四通道+8052+lcd1602实现

1 篇文章 0 订阅
1 篇文章 0 订阅

这是我的启蒙设计
用的语法都比较简单希望能帮到大家
仿真和源代码在最后面

//ad0808(仿真)对应实物为adc0809采样电压数据并转化成十进制在LCD1602上面显示出来精确度为5/255约等于0.02
//1.头文件,宏定义,定义管脚等:
#include <REGX52.H>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define uchar unsigned char
#define uint unsigned int
//1602的使能,读写的三个端口
sbit EN=P3^2;
sbit RW=P3^3;
sbit RS=P3^4;

sbit clk=P2^4;     //时钟,adc0809工作时要有时钟
sbit START=P2^5;   //产生一个脉冲后adc0808开始工作
sbit ad_busy=P2^6;     //转换完成会反转
sbit OE=P2^7;       //adc的开关

uint tmp;              
uint tmp1;
uint tmp2;              
uint tmp3;
//sbit P2_0=P2^0;
//sbit P2_1=P2^1;
//sbit P2_2=P2^2;
//sbit P2_3=P2^3;

uchar code table[]={'0','1','2','3','4','5','6','7','8','9'};  //此条语句为显示字符串时定义的字符串数组

//2.延时子程序:
void delay(uint c)    //功能为提供初始化等其他子程序中的延时
{
  uint a,b;
  for(a=0;a<c;a++)
  for(b=0;b<120;b++);
}

//3.LCD1602基本初始化子程序:
void LCD1602()
{
 EN=0;
 RS=1;
 RW=1;
 P0=0xff;   //这里P0为与LCD D0~D7相连的I/O口
}
 
//4.读忙子程序:实物连接可以不用屏蔽,但是仿真必须屏蔽
//void read_busy()
//{
//  P0=0xff;
//  RS=	0;
//  RW=1;
//  EN=1;
//  while(P0&0x80);   //P0和10000000相与,D7位若不为0,停在此处
//  EN=0;             //若为0跳出进入下一步;这条语句的作用就是检测D7位}                
//}

//5.写指令写数据子程序:
void write(uchar a,bit b)
{
//  read_busy(); //读忙函数仿真要屏蔽
	delay(10);
  P0=a;  
  RS=b;   //其中a=0,写指令;b=1,写数据;
  RW=0;  
  EN=1;
  EN=0;
}

//6.LCD1602初始化子程序:
void init()    //完全按照要求初始化流程来,中间省略了一步写指令38H
{
  delay(15);
  write(0x38,0);
  delay(5);
  write(0x38,0);
  write(0x08,0);
  write(0x01,0);
  write(0x06,0);
  write(0x0c,0);
}

//7.定时器T0外部中断1用于adc0809
void Interrupt() interrupt 1
{
    TH0 = (65536 - 50) / 256; //触发中断时重新装填计时
    TL0 = (65536 - 50) % 256;
    clk = ~clk;
}
	
//8.显示单个字符子程序:
void display_lcd_byte(uchar y,uchar x,uchar z)    //Y=0,1(起始行)X=0~15(起始列)Z=想写字符的ASCII码
{         
if(y)	//是否显示在第二行(若在第一行Y=0,不进入IF语句,若在第二行,进入IF语句
  {        
   x+=0x40;   //第二行起始地址加上列数为字符显示地址
  }
  x+=0x80;      //设置数据指针位置
  write(x,0);  
  write(z,1);   //写入数据
}

//9.显示字符串子程序:
void display_lcd_text(uchar y,uchar x,uchar table[])    //Y,X同上字符显示,table[]字符串数组 
{      
  uchar z=0;
  uchar t;
  t=strlen(table)+x;   //  求得字符串长度加上起始列位置
  while(x<t)        //功能为LCD显示到字符串最后一个字符,防止字符串
  {                 //没有16个字符,从而不够位产生乱码;
    display_lcd_byte(y,x,table[z]);    //逐位显示数组内字符
    x++;
    z++;
  }
}
//10.将8位的ADC转换成十进制并逐次显示出来,这里可以使用sprintf函数来转换只要添加相应的头文件(有时间我会去改改),为了更直观的理解采用以下的方法
void mul_adc(uint a,uint b,uint c)
{
#if 1 //将1改成0就可以用下面的方式了
	uint i;      //0 - 255.例如当1.25V时   x/255=1.25/5  x=63.75  
	c=c/0.051;   //小数点去掉,应为64左右。同理得出输入2V时,输出转
	i=c/1000;    //换数据为102.out=x*5/255.out=out*1000(保留3位小数).
	display_lcd_byte(a,(b),table[i]);
	delay(10);
	display_lcd_byte(a,(b+1),'.');
	delay(10);
    i=c/100%10;
	display_lcd_byte(a,(b+2),table[i]);
	delay(10);
	i=c/10%10;
	display_lcd_byte(a,(b+3),table[i]);
	delay(10);
#else
//sprintf的实现将上面的uint i;到delay(10);都屏障了,以下的四条语句即可实现上述功能并且更加灵活
		char n[10];  //定义一个缓存
		float i=c/51.0;//将c的值即采样的值转化成float型的电压值即实际电压值
		sprintf(n,"%.2f",i);//将电压值转化成字符串的形式
		display_lcd_text(a,b,n);//直接在坐标(a,b)位置打印
#endif
}
//11.显示数据的位置
void show ()  
{
mul_adc(0,3,tmp);
mul_adc(1,3,tmp1);
mul_adc(0,11,tmp2);
mul_adc(1,11,tmp3);

}

//12.主程序:主程序里除了放入初始化程序外就是加入自己编写的显示子程序
void main()
{
  LCD1602();
	delay(50);
  init();
  clk = 0xff;  //初始化clk
  TMOD = 0x01; //初始化TMOD,定时器0,方式1
  EA = 1; //开放所有中断
  ET0 = 1; //开放定时器0中断控制位
  TR0 = 1; //定时器0开始计时
	while(1)
	{
		
	P2_0=0;     //ADC通道0打开 P2_1,P2_2接地,ADD(ABC)=000;
	P2_1=0;
  START=0;    
	START=1;     //0 1 0为一个脉冲
	START=0;	   //ADC开始工作
	while(ad_busy==1);  //ADC转换完成标志
  OE=0;               //
	delay(20);         //0->1上升沿开 adc必须有延时否则单片机反应不过来 
	OE=1;               //
	tmp=P1;
	OE=0;               //1->0下降沿关
	
    P2_0=1;//ADC通道1打开ADD(ABC)=001;
	P2_1=0;
	START=0;
	START=1;
	START=0;
	while(ad_busy==1);
	delay(20);
	OE=1;	
	tmp1=P1;
	OE=0;
	
	P2_0=0;//ADC通道2打开ADD(ABC)=010;
	P2_1=1;
	START=0;
	START=1;
	START=0;
	while(ad_busy==1);
	delay(20); 	
	OE=1;
	tmp2=P1;
	OE=0;
	
	P2_0=1; //ADC通道3打开ADD(ABC)=011;
	P2_1=1;
	START=0;
	START=1;
	START=0;
	while(ad_busy==1);
	delay(20);
	OE=1;
	tmp3=P1;
  OE=0;
	
  display_lcd_text(0,0,"U0:");    //  显示字符串
	display_lcd_byte(0,7,'V');      //  显示一个字符
	
  display_lcd_text(0,8,"I0:");    //  显示字符串
	display_lcd_byte(0,15,'A');      //  显示一个字符
	
	display_lcd_text(1,0,"U1:");    //  显示字符串
	display_lcd_byte(1,7,'V');      //  显示一个字符
	
	display_lcd_text(1,8,"I1:");    //  显示字符串
	display_lcd_byte(1,15,'A');      //  显示一个字符
	
  show();
	
  }
}
 


 


 


 

在这里插入图片描述链接:https://pan.baidu.com/s/1e2lt4N2GCB9CCKAIhVUT1Q
提取码:zq4g

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ADC(模数转换器)是一种用于将模拟信号转换为数字信号的电路。在单通道电压采集中,我们可以使用ADC来转换输入电压。在这里,我将提供一个使用stm32f4xx系列芯片和lcd1602.h头文件的ADC实现通道电压采集的示例代码。请注意,具体实现可能会因芯片型号和硬件连接方式而异。 ```c #include "stm32f4xx.h" #include "lcd1602.h" ADC_HandleTypeDef hadc1; /* ADC1初始化函数 */ static void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; /** 配置ADC1的时钟使能 */ __HAL_RCC_ADC1_CLK_ENABLE(); hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** 配置ADC1通道0的采样参数 */ sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } /* 获取ADC1的采样值 */ uint16_t Get_ADC1_Value(void) { HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 100); uint16_t adc_value = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return adc_value; } /* 初始化LCD1602 */ void Init_LCD1602(void) { /* 初始化GPIO */ Init_GPIO(); /* 初始化LCD1602 */ LCD1602_Init(); } int main(void) { HAL_Init(); MX_ADC1_Init(); Init_LCD1602(); /* 显示采样值 */ uint16_t adc_value; char buffer[16]; while (1) { adc_value = Get_ADC1_Value(); sprintf(buffer, "ADC value:%d", adc_value); LCD1602_DisplayStringLine(0, buffer); HAL_Delay(1000); LCD1602_ClearScreen(); } } ``` 在这个例子中,我们首先使用MX_ADC1_Init函数初始化ADC1,然后使用Get_ADC1_Value函数获取ADC1的采样值。我们将采样显示LCD1602上,以便进行观察。最后,我们使用HAL_Delay函数在每次采样后延迟1秒,并使用LCD1602_ClearScreen函数清除LCD屏幕以便进行下一次采样。 请注意,这只是一个示例代码,实际应用中可能需要进行更多的初始化和配置。同时,硬件连接也需要与代码相对应。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值