运用STM32F103和LCD1602实现实时显示电压的功能
ADC运用的管脚是 PA(0)
下面是ADC的配置
#include "ADC.h"
void ADC_Init_MY(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);//重置ADC校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待重置结束
ADC_StartCalibration(ADC1);//开始校准ADC
while(ADC_GetCalibrationStatus(ADC1));//等待校准结束
}
接下来我们配置LCD1602
#include "LCD1602.h"
#include "delay.h"
void LCD1602_Init(void)
{
// D0<--> B11
// D1<--> B10
// D2<--> B1
// D3<--> B0
// D4<--> A7
// D5<--> A6
// D6<--> A5
// D7<--> A4
// RS<-->A3
// E<--> A2
// RW<-->A1
// V0<-->电阻接地
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);//开启PA和PB GPIO的 时钟
//配置PA0~7为推挽式输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置PB0 1 10 11为推挽式输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_10 |GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void LCD1602_Write_Cmd(unsigned char cmd)
{
LCD_RS = 0;
LCD_RW = 0;
delay_ms(1);
LCD_E = 1;
LCD_D0 = cmd>>0;
LCD_D1 = cmd>>1;
LCD_D2 = cmd>>2;
LCD_D3 = cmd>>3;
LCD_D4 = cmd>>4;
LCD_D5 = cmd>>5;
LCD_D6 = cmd>>6;
LCD_D7 = cmd>>7;
delay_ms(1);
LCD_E = 0;
delay_ms(1);
}
void LCD1602_Write_Date(unsigned char date)
{
LCD_RS = 1;
LCD_RW = 0;
delay_ms(1);
LCD_E = 1;
LCD_D0 = date>>0;
LCD_D1 = date>>1;
LCD_D2 = date>>2;
LCD_D3 = date>>3;
LCD_D4 = date>>4;
LCD_D5 = date>>5;
LCD_D6 = date>>6;
LCD_D7 = date>>7;
delay_ms(1);
LCD_E = 0;
delay_ms(1);
}
这里遇到的问题是E0管脚接电阻接地所接的电阻值的大小,这个阻值最好不大于5K不小于500R,太大了显示的内容太淡,阻值太小全是方块,看不清显示的内容,好像每一块1602的最佳阻值都不一样,最好使用电位器自己调试。
下面是我的主程序
#include "sys.h"
#include "ADC.h"
#include "usart.h"
#include "delay.h"
#include "LCD1602.h"
#include "string.h"
u16 ADC_BUF = 0;
u8 i = 0;
float v = 0;
unsigned char str_T[10] = {0};
int main(void)
{
delay_init();
uart_init(115200);
ADC_Init_MY();
LCD1602_Init();
LCD1602_Write_Cmd(0x38);//配置16*2显示,5*7点阵,8位数据接口
LCD1602_Write_Cmd(0x0C);//设置开显示,不显示光标
LCD1602_Write_Cmd(0x06);//写字符后地址自动加1
LCD1602_Write_Cmd(0x01);//显示清0,数据指针清0
while(1)
{
/************ADC****************/
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_FLAG_EOC);
ADC_BUF = ADC_GetConversionValue(ADC1);
v = 3.3*ADC_BUF/4095;
printf("Volt %fV\r\n",v);
delay_ms(500);
sprintf(str_T,"U:%fV",v);
/*********LCD1602***********/
LCD1602_Write_Cmd(0X80+0X00);//显示在第1行第一个
for(i = 0;i<strlen(str_T);i++)
{
LCD1602_Write_Date(str_T[i]);
}
}
}
以上的程序测试过可以使用,下面附一张显示图,我的采样方式是将两个阻值一样的电阻分别接VCC和GND,从中间引出一根线接PA(0)