1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > stm32+LCD12864+ADC实现将ADC采样的值实时显示

stm32+LCD12864+ADC实现将ADC采样的值实时显示

时间:2023-12-16 10:22:47

相关推荐

stm32+LCD12864+ADC实现将ADC采样的值实时显示

前言

这篇文章以上一篇文章为基础,着重讲如何将ADC采样得到的值显示在LCD12864上面,关于如何点亮LCD屏幕,以及实物硬件连线图、原理,请参考之前一篇文章。加上上一篇文章,这算是一个十分迷你的项目了~还有一个比较常用且重要的知识点就是sprintf()函数的使用——在stm32的编程中如何将浮点小数转换成字符串打印。废话不多说,放码吧!

代码

1.lcd.h部分

#ifndef _LCD_H#define _LCD_H#include "sys.h"#include "delay.h"#define RS PCout(0) //发数据/命令控制口#define RW PCout(1) //读/写控制口,写比较常用#define EN PCout(2) //使能口#defineLINE10x80 //第一行起始地址,下同#defineLINE2 0x90#defineLINE3 0x88#defineLINE4 0x98//以下是点亮你的屏幕必要的六个函数,不能再少了,想添加其他功能就得再加其他函数void IO_Init(void); //必要的IO口初始化void CheckBusy(void); //检查忙/闲状态void LCD_wdat(u8 dat); //写数据void LCD_wcmd(u8 com); //写命令void LCD_Init(void); //LCD初始化void LCD_Wmessage(u8* message,u8 address); //向屏幕里写入字串#endif

2.lcd.c部分

#include "lcd.h"#include "sys.h"#include "delay.h"u16 temp;void IO_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);//想实现控制,激活控制口(PC0,PC1,PC2)必不可少GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);//想发送数据,激活数据口(PA0~PA7)必不可少GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);}//LCD初始化void LCD_Init(){LCD_wcmd(0x30);//功能设定:基本指令集delay_ms(5);LCD_wcmd(0x0C);//显示开,关光标delay_ms(5);LCD_wcmd(0x01);//清除显示}//忙判断void CheckBusy(void){u8 status;RS=0;RW=1; //读出数据,RW=1GPIOA->ODR = 0xFF;do{EN = 1;delay_ms(5);status = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7);//接收BF位,判断是否忙}while(status & 0x80);EN=0;}//LCD写命令void LCD_wcmd(u8 cmd){CheckBusy();RS=0;RW=0;delay_ms(5);temp=(temp&0xff00)|cmd;//temp的低八位清零后将cmd放进去GPIO_Write(GPIOA,temp);//通过GPIO_Write()函数将数据发到A端口(也就是LCD的数据口)EN=1;//使能位开启delay_ms(10);//10ms应该能发送完了EN=0;//使能位关闭}//LCD写数据void LCD_wdat(u8 dat){CheckBusy();RS=1;RW=0;delay_ms(5);temp=(temp&0xff00)|dat; //temp的低八位清零后将dat放进去GPIO_Write(GPIOA,temp);//通过GPIO_Write()函数将数据发到A端口(也就是LCD的数据口)EN=1;//使能位开启delay_ms(10);//10ms应该能发送完了EN=0;//使能位关闭}//向LCD12864中写入一行数据(因为你不可能每次只发送一字节数据)void LCD_Wmessage(u8* message,u8 address){LCD_wcmd(address);//要显示的位置,你想让内容显示在LCD的哪一行,就把该行的起始地址通过写命令的方式发送出去,很神奇,有木有while(*message>0)//这个判断很关键,判断你的内容有没有发完{LCD_wdat(*message); //内核还是发字节函数message++; //指针挺好用的。。}}

3.adc.h和lcd.c部分随便参照原子哥的一个ADC例程即可,我也是直接拿过来用的。。采样的是战舰V3板载的光敏电阻

adc.h文件:

#ifndef __ADC_H#define __ADC_H#include "sys.h"#include "stm32f10x.h"void Adc_Init(void);u16 Get_Adc(u8 ch);u16 Get_Adc_Average(u8 ch,u8 times);#endif

4.adc.c

#include "adc.h"#include "stm32f10x.h"#include "delay.h"#include "stdio.h"#include "stdlib.h"#include "string.h"void Adc_Init(){ADC_InitTypeDef ADC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF|RCC_APB2Periph_ADC3, ENABLE );//RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12MHZ(不分频好像也没事,现象和分频现象一致。好像有个默认的分频)GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;GPIO_Init(GPIOF,&GPIO_InitStructure);ADC_DeInit(ADC3); //复位ADC1 ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;ADC_InitStructure.ADC_NbrOfChannel=1;ADC_InitStructure.ADC_ScanConvMode=DISABLE;ADC_Init(ADC3,&ADC_InitStructure);ADC_Cmd(ADC3, ENABLE);//使能指定的ADC3ADC_ResetCalibration(ADC3);//重置指定的ADC3的复位寄存器while(ADC_GetResetCalibrationStatus(ADC3));//获取ADC1重置校准寄存器的状态,设置状态则等待ADC_StartCalibration(ADC3);while(ADC_GetCalibrationStatus(ADC3));//获取指定ADC1的校准程序,设置状态则等待}u16 Get_Adc(u8 ch){ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_239Cycles5 );ADC_SoftwareStartConvCmd(ADC3, ENABLE);//使能指定的ADC3的软件转换启动功能while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC ));//等待转换结束return ADC_GetConversionValue(ADC3);//返回最近一次ADC3规则组的转换结果}u16 Get_Adc_Average(u8 ch,u8 times){u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}temp_val=temp_val/times;return temp_val;}

5.最后就是主函数部分了。前面的代码比较简单,主函数最重要的一个作用就是对接收到的数据进行处理。其中一个就是如何把ADC得到的数字以一个字符串的方式在LCD屏幕上打印出来。这花了我一些时间去找解决方法(因为水平比较烂,所以很多都得找着学~),后来找到了解决方法,就是开头说的sprintf()函数。先把代码发出来:

#include "stm32f10x.h"#include "sys.h"#include "lcd.h"#include "delay.h"#include "usart.h"#include "adc.h"/************************一行16个字节,一个汉字2字节,一个字母1字节,每个汉字只能在偶字节处起************************/int main(void){u8 dis1[]={"µ±Ç°µç×èÖµ£º"};u16 adcx;float temp;u8 aa[10];uart_init(115200);Adc_Init();delay_init();IO_Init();LCD_Init();while(1){adcx=Get_Adc_Average(ADC_Channel_6,10);temp=(float)adcx*(3.3/4096);//printf("adcx: %5.3f",temp);//向串口打印验证用sprintf(aa,"%5.3f",temp);LCD_Wmessage(dis1,LINE1);LCD_Wmessage(aa,LINE2+2);}}

可以看到,sprintf()函数一共有三个参数,第一个参数是我们要的(字符串类型),第二个为格式化输出的形式,第三个是待处理的数据(浮点型数据)。因为LCD最终接受的要打印的数据为字符串,所以我们AD采样得到的浮点数据不可以直接发送给LCD_Wmessage()函数,必须经过这样一次处理才能将其打印(一时没想起其他的方法,欢迎有其他方法的伙伴交流进步)。

最后呈现的结果如下:

(没开手电筒时)

(打开手电筒后)

完。欢迎大家一起交流,共同进步。

由于时间太久还是有同学来问我要这个工程,而且CSDN自动把这个资源的积分加的太多,所以现在把百度云连接贴出来,大家有需要自行下载(如果你不介意,可以给我点个赞👍哈哈)。

链接:/s/16Wckkp6pZrIxPoffB1DDyw

提取码:f4m0

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。