电压检测_电压检测电路 - CSDN
精华内容
参与话题
  • STM32F4的电压实时检测

    千次阅读 2019-03-06 09:05:04
    本人最近课程设计学习STM32F4系列,在此进行学习...B:通过旋转滑动变阻器改变电压,随着电压的不同,通过点亮LED灯发出警告,当电压达到最大值,蜂鸣器叫。 C:串口输出当前电压值。 二、过程 1、代码风格 考虑该项目...

    本人最近课程设计学习STM32F4系列,在此进行学习记录!本次记录完成的结课项目!
    课程实训涉及STM32基本知识,GPIO,外部中断EXTI,串口USART,ADC以及DMA,最后贴有注解代码!

    一、任务

    A:按键控制ADC开始工作
    B:通过旋转滑动变阻器改变电压,随着电压的不同,通过点亮LED灯发出警告,当电压达到最大值,蜂鸣器叫。
    C:串口输出当前电压值。

    二、过程

    1、代码风格

    考虑该项目相当于于之前的实验来说,体量更大,所以在编写代码的时候,分成了main函数,头文件,函数定义c文件三个部分。使代码更便于阅读与修改。在.h文件中对函数进行声明,在.c文件对所有函数进行定义。
    在这里插入图片描述

    2、volatile类型理解

    volatile是一个类型修饰符(type specifier),在库函数的代码中定义位“__IO”。volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
    volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
    而在使用ADC读取实时读取电压值的时候就应该使用该类型。

    3、小问题

    1、串口中断标志

    只需要发和收,所以在发的时候不需要中断否则会程序无功能。

    2、外部变量的使用

    应该在主函数中定义变量,然后在其他.c文件中使用extern来使用外部变量进行传参。否则会导致传参失败。

    3、RCC的知识

    在使用RCC时钟配置函数,应该在main函数中首先调用,否则会出错。

    三、成果

    圆满完成了项目要求。
    在对STM32复位后,初始化ADC是关闭的,串口打印出“ADC DID NOT OPEN”的信息。
    在这里插入图片描述

    当按下了WAKEUP KEY之后,通过外部中断EXTI响应打开了ADC,串口打印出“OPEN THE ADC”信息,并实时发送电压信息。

    图6-5 ADC打开
    通过调节电位器旋钮进行LED灯的点亮,其中电压比小于25,点亮一盏灯;电压比小于50,点亮两盏灯;电压比小于75,点亮3盏灯,电压比大于75,四盏灯全亮,当电压比达到98及更高的时候,蜂鸣器鸣叫。

    在这里插入图片描述

    四、代码

    1、main.c文件

    #include <stdio.h>
    #include "main.h"
    #include "project_fun.h"
    
    __IO uint16_t ADC1ConvertedValue = 0;
    int flag=0;
    
    int main()
    {
    	u16 ADCConvertedValueLocalTemp, ADCConvertedValueLocal, Precent = 0, Voltage = 0;
    	
    	RCC_config();
    	led_config();			
    	bee_config();
    	Res_config();
    	GPIO_config();
    	NVIC_config();
    	exti_config();
    	key_init();
    	uart_config();
    	DMA_Configuration();
    	ADC_Config();
    	
    	Delay_ARMJISHU(6000000);
    	
    	ADC_SoftwareStartConv(ADC1);
    	
    	while(1)
    	{  
    		if(flag==1)
    		{
    	    ADCConvertedValueLocalTemp = ADC1ConvertedValue;//第一次得到ADC采取到的值
    			Delay_ARMJISHU(80000);
    			ADCConvertedValueLocal = ADC1ConvertedValue;//第二次得到ADC采取到的值
    			//取两个数采样平均值
    			ADCConvertedValueLocal = (ADCConvertedValueLocalTemp + ADCConvertedValueLocal)/2;
    			
    			Precent = (ADCConvertedValueLocal*100/0x1000);
    			Voltage = Precent*33;						  
    			printf("\r Result:0x%X, Percentage:%d%%, Voltage:%d.%d%dV.  \r", 
    			ADCConvertedValueLocal, Precent, Voltage/1000, (Voltage%1000)/100, (Voltage%100)/10);
    		
    			if(Precent<=25)
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_10);
    				GPIO_SetBits(GPIOF,GPIO_Pin_9);
    				GPIO_SetBits(GPIOF,GPIO_Pin_8);	
    				GPIO_SetBits(GPIOF,GPIO_Pin_7);
    				GPIO_SetBits(GPIOF,GPIO_Pin_6);
    			}
    			else if(Precent<=50&&Precent>25)
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_10);
    				GPIO_ResetBits(GPIOF,GPIO_Pin_9);
    				GPIO_SetBits(GPIOF,GPIO_Pin_8);	
    				GPIO_SetBits(GPIOF,GPIO_Pin_7);
    				GPIO_SetBits(GPIOF,GPIO_Pin_6);
    			}
    			else if(Precent<=75&&Precent>50)
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_10);
    				GPIO_ResetBits(GPIOF,GPIO_Pin_9);
    				GPIO_ResetBits(GPIOF,GPIO_Pin_8);	
    				GPIO_SetBits(GPIOF,GPIO_Pin_7);
    				GPIO_SetBits(GPIOF,GPIO_Pin_6);
    			}
    			else
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_10);
    				GPIO_ResetBits(GPIOF,GPIO_Pin_9);
    				GPIO_ResetBits(GPIOF,GPIO_Pin_8);	
    				GPIO_ResetBits(GPIOF,GPIO_Pin_7);
    				GPIO_SetBits(GPIOF,GPIO_Pin_6);
    				if(Precent>=99)
    				{
    					GPIO_ResetBits(GPIOF,GPIO_Pin_6);
    				}					
    			}
    			Delay_ARMJISHU(6000000);	
    		}
    		else
    		{
    			GPIO_SetBits(GPIOF,GPIO_Pin_10);
    			GPIO_SetBits(GPIOF,GPIO_Pin_9);
    			GPIO_SetBits(GPIOF,GPIO_Pin_8);	
    			GPIO_SetBits(GPIOF,GPIO_Pin_7);
    			GPIO_SetBits(GPIOF,GPIO_Pin_6);
    			Delay_ARMJISHU(10000000);
    			printf("\n\t ADC did not open! \n\t");
    			Delay_ARMJISHU(60000000);
    		}
    	}
    }
    
    
    

    2、project_fun.h文件

    #ifndef __PROJECT_FUN_H
    #define __PROJECT_FUN_H
    
    #include "main.h"
    
    void Delay_ARMJISHU(__IO uint32_t nCount);
    void RCC_config(void);
    void led_config(void);
    void bee_config(void);
    void exti_config(void);
    void NVIC_config(void);
    void key_init(void);
    void Res_config(void);
    int fputc(int ch, FILE *f);
    int fgetc(FILE *f);
    void uart_config(void);
    void usart_sendbyte(USART_TypeDef* USARTx,uint16_t ch);
    void usart_sendstring(USART_TypeDef* USARTx,char * str);
    void GPIO_config(void);
    void ADC_Config(void);
    void DMA_Configuration(void);
    
    
    #endif
    
    

    3、project_fun.c文件

    #include <stdio.h>
    #include "main.h"
    
    #define ADC_DR_ADDR  ((uint32_t)(0x4001204C)) //ADC1的地址
    
    extern __IO uint16_t ADC1ConvertedValue;//定义变量
    extern int flag;
    
    
    void Delay_ARMJISHU(__IO uint32_t nCount)
    {
      for (; nCount != 0; nCount--)
      {
      }
    }
    
    
    //led灯配置
    void led_config(void)
    {
    	//定义初始化结构体
    	GPIO_InitTypeDef  GPIO_InitStruct;
    	
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    
    	//led初始化函数
    	GPIO_Init(GPIOF,&GPIO_InitStruct);
    	
    
    	
    	//初始化灯先关闭,取反操作
    	GPIO_SetBits(GPIOF,GPIO_Pin_10);
    	GPIO_SetBits(GPIOF,GPIO_Pin_9);
    	GPIO_SetBits(GPIOF,GPIO_Pin_8);	
    	GPIO_SetBits(GPIOF,GPIO_Pin_7);
    	
    }
    
    //蜂鸣器配置
    void bee_config(void)
    {
    	//蜂鸣器对应GPIO口结构体初始化
    	GPIO_InitTypeDef  GPIO_InitStruct;
    	
    	//结构体赋值
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz ;
    	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	
    	
    	//初始化函数
    	GPIO_Init(GPIOF,&GPIO_InitStruct);
    	
    	//初始化蜂鸣器先关闭
    	GPIO_SetBits(GPIOF,GPIO_Pin_6);
    	//GPIOF->ODR ^=  GPIO_Pin_6;GPIO_SetBits(GPIOF,GPIO_Pin_6);
    }
    
    void Res_config(void)
    {
    	GPIO_InitTypeDef  GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
    	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	GPIO_Init(GPIOC,&GPIO_InitStruct);
    }
    
    
    //时钟初始化配置
    void RCC_config(void)
    {
    	//时钟线给予GPIOF口确定
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
    	
    	//需要给予外部中断映射时钟线
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
    	
    	//给予按键时钟线
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); 
    	
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); 
    	
    	//给予串口时钟,因为串口是PA口
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    	
    	//给予GPIOA口时钟,因为串口USART使用了PA9,PA10口,同样需要给予时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    	
    	//给予DMA2时钟线
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    	
    	
    	//给予ADC1时钟线
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    	
    }
    
    
    
    //外部中断配置
    void exti_config(void)
    {
    	//初始化外部中断结构体
    	EXTI_InitTypeDef EXTI_InitStruct; 
    	
    	//输入结构体参数
    	EXTI_InitStruct.EXTI_Line = EXTI_Line0;
    	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
    	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    	
    	
    	//外部中断需要端口映射
    	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
    	
    	EXTI_Init(&EXTI_InitStruct);	
    	
    }
    
    
    //按键初始化配置
    void key_init()
    {
    	//按键对应GPIO口结构体初始化
    	GPIO_InitTypeDef  GPIO_InitStruct;	
    	
    	//结构体参数配置
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    
    	//初始化函数
    	GPIO_Init(GPIOA,&GPIO_InitStruct); 
    }
    
    //串口GPIO初始化配置
    void GPIO_config(void)
    {
    	//定义使用串口的GPIO口
    	GPIO_InitTypeDef GPIO_InitStruct;
    	
    	//通过核心板找到对应的串口的引脚
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; 
    	//模式的使用是AF复用模式
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    	//输出方式使用推挽输出
    	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    	
    	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    	//设置速度
    	//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	
    	//初始化GPIO9的引脚
    	GPIO_Init(GPIOA,&GPIO_InitStruct); 
    	
    	
    	//初始化GPIO10的引脚,其他都一样
    	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;	
    	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    	//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStruct); 
    	
    	//GPIO口的引脚的复用功能需要该函数进行对应匹配
    	//GPIO口的核心板上的引脚也是
    	//其不同于中断的sys函数,并不是映射
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
    }
    
    
    //NVIC中断模块管理初始化
    void NVIC_config(void)
    {
    	//NVIC结构体初始化
    	NVIC_InitTypeDef NVIC_InitStruct;
    	
    	//NVIC模块分组
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);	
    	
    	
    	//结构体参数配置
    	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    	
    	//NVIC初始
    	NVIC_Init(&NVIC_InitStruct);  
    	
    	//选择串口中断通道
    	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    	
    	//NVIC初始
    	NVIC_Init(&NVIC_InitStruct);  
    }
    
    
    //串口配置
    void uart_config(void)
    {
    	//定义串口初始化的结构体
    	USART_InitTypeDef USART_InitStruct;
    	
    	
    	//波特率设置
    	USART_InitStruct.USART_BaudRate = 115200;
    	//硬件流控制
    	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    	//模式选择,包含Tx与Rx
    	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    	//校验位,本实验没有使用校验
    	USART_InitStruct.USART_Parity = USART_Parity_No;
    	//指定传输的停止位
    	USART_InitStruct.USART_StopBits = USART_StopBits_1;
    	//数据长度
    	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    	
    	
    	
    	//串口初始化函数,参数使用的是USART1。
    	USART_Init(USART1,&USART_InitStruct);
    	
    	
    	//对串口进行使能,打开串口外设
    	USART_Cmd(USART1,ENABLE);   
    	//对串口进行使能,打开串口中断
    	//其中参数需要同时有收,发的操作,所以是或操作
    	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
    }
    
    
    
    //串口发送数据函数
    void usart_sendbyte(USART_TypeDef* USARTx,uint16_t ch)
    {
    	//发送字符
    	USART_SendData(USARTx, ch); 
    	//如果没有发送到数据,即是RESET,在此处等待,判定标志
    	while(USART_GetITStatus(USARTx,USART_FLAG_TXE) == RESET);
    }
    
    
    //串口发送字符串函数
    void usart_sendstring(USART_TypeDef* USARTx,char * str)
    {
    	//通过字符串指针名自加的操作方式一一打印出字符
    	do{
    		usart_sendbyte(USARTx,*str);
    		str++;
    	}while(*str!='\0');
    	//如果没有发送到数据,即是RESET,在此处等待
    	while(USART_GetITStatus(USARTx,USART_FLAG_TXE) == RESET);
    }
    
    
    
    //重定向printf函数
    //此函数原本是将字符ch打印到文件指针stream流中去,现在是打印到串口1
    //使用printf即可以进行串口信息的发送了
    int fputc(int ch,FILE *f)
    {
    			USART_SendData(USART1, ch); 
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);//表示发送完成的FLAG
    		return ch;
    }
    
    //重定向scanf函数
    int fgetc(FILE *f)
    {
    	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == RESET);
    	return USART_ReceiveData(USART1);
    }
    
    //ADC初始化配置
    void ADC_Config(void)
    {
    	//在此情况下的ADC默认采集的是系统的电压,我们即可以通过调节电位器实现不同数据的实现
    	//ADC通用结构体初始化
    	ADC_CommonInitTypeDef ADC_CommonInitStruct;
    	//ADC结构体初始化
    	ADC_InitTypeDef ADC_InitStruct;
    
    	
    	//配置结构体参数
    	ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;	//ADC独立模式
    	ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;	//禁止DMA直接传输模式
    	ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2;	//时钟2分频
    	ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;	//采样时间间隔
    	
    	//通用结构初始化函数
    	ADC_CommonInit(&ADC_CommonInitStruct);
    	
    	//配置结构体参数
    	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;	//ADC使能
    	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;	//数据右对齐
    	ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止外部边沿触发
    	ADC_InitStruct.ADC_NbrOfConversion = 1;	//转换通道数目为1
    	ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;	//分辨率12位
    	ADC_InitStruct.ADC_ScanConvMode = DISABLE;//禁止扫描
    	
    	//ADC函数初始化
    	ADC_Init(ADC1,&ADC_InitStruct);
    	
    	ADC_RegularChannelConfig(ADC1,ADC_Channel_13,1,ADC_SampleTime_3Cycles);	//配置ADC的通道转换顺序
    	ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);//使能DMA请求
    	ADC_DMACmd(ADC1,ENABLE);//使能ADC的DMA传输模式
    	
    	
    	ADC_Cmd(ADC1,ENABLE);	//ADC使能
    
    }
    
    
    void DMA_Configuration(void)
    {
    	
    	//DMA结构体初始化
    	DMA_InitTypeDef DMA_InitStruct;
    	
    	//DMA是存储器与外设传输的控制器
    	//初始化DMA结构体(使用DMA2)
    	//由DMA2表格有,应该数据流0通道0才能使用ADC1
    	DMA_InitStruct.DMA_Channel = DMA_Channel_0;	//DMA通道0
    	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC_DR_ADDR;	//给予ADC1的基地址
    	DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;	//声明的变量的存储器地址
    	DMA_InitStruct.DMA_BufferSize = 1;	//传输数据大小为1
    	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;	//传输的方向
    	DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;	//循环传输
    	DMA_InitStruct.DMA_Priority = DMA_Priority_High;	//优先级
    	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	//外设字长
    	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	//存储器字长
    	DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;	//单次传输
    	DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;	//单次传输
    	//因为保证了存储器与外设的字长,所以并不需要下述的模式,均给予Disable
    	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;	//不给予外设增量
    	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable;	//不给予存储器增量
    	DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;	//不给予FIFO模式
    	
    	//初始化函数,使用DMA2的流0,在之前结构体定义了使用的是通道0,查表得到对应的ADC1
    	DMA_Init(DMA2_Stream0,&DMA_InitStruct);
    	//进行使能
    	DMA_Cmd(DMA2_Stream0,ENABLE);
    }
    
    
    //外部中断响应函数
    void EXTI0_IRQHandler(void)
    {
    	//中断响应判定标志
    	if(EXTI_GetITStatus(EXTI_Line0) != RESET )
    	{
    		Delay_ARMJISHU(6000000);
    		//对应IO口取反
    		//GPIOF->ODR ^=  GPIO_Pin_10;
    		//GPIOF->ODR ^=  GPIO_Pin_6;
    
    		
    		if(flag==0)
    		{
    			DMA_Cmd(DMA2_Stream0,ENABLE);
    			ADC_Cmd(ADC1,ENABLE);	//ADC使能
    			ADC_DMACmd(ADC1,ENABLE);//使能ADC的DMA传输模式
    			flag=1;
    		//清楚中断标志
    			printf("\nOpne the ADC!\n");
    		}
    		else
    		{
    			DMA_Cmd(DMA2_Stream0,DISABLE);
    			ADC_Cmd(ADC1,DISABLE);	//ADC使能
    			ADC_DMACmd(ADC1,DISABLE);
    			flag=0;			
    			printf("\nClose the ADC!\n");
    		}
    		EXTI_ClearITPendingBit(EXTI_Line0);
    		
    	}
    }
    
    //串口中断响应函数
    void USART1_IRQHandler(void)
    {
    	uint16_t ch;
    	//进行接受数据的操作
    	if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)//if语句判定串口响应标志
    	{
    		ch = USART_ReceiveData(USART1);//接受字符ch
    		USART_SendData(USART1,ch);
    		USART_ClearFlag(USART1,USART_FLAG_RXNE); //清楚标志位
    	}
    }
    
    
    
    
    展开全文
  • 串联电池组广泛应用于手携式工具、笔记本电脑、通讯电台以及便携...为了使电池组的可用容量最大化及提高电池组的可靠性,电池组中的单体电池性能应该一致,从而需对单体电池进行监控,即需要对单体电池的电压进行测量。
  • 关于电池电压检测

    千次阅读 2019-06-30 00:22:18
    1s电池电压是3.7V,2s电池就是有两块电池,电压是3.7*2=7.4V,以此类推,锂离子电池一般3.7V-4.2V 百分比---电压*分压系数--测得值---转换为数字(0-255) -------1S 100% -- -4.2v * 2/3 –-2.8v------216 80%--...

    1s电池电压是3.7V,2s电池就是有两块电池,电压是3.7*2=7.4V,以此类推,锂离子电池一般3.7V-4.2V

    百分比---电压*分压系数--测得值---转换为数字(0-255)           -------1S

    100% -- -4.2v * 2/3 –-2.8v------216

    80%-----3.98V* 2/3 –-2.65v------205

    60%-----3.87V* 2/3 –-2.58v------199

    40%-----3.79V* 2/3 –-2.52v------195

    20%-----3.74V* 2/3 –-2.49v------192

    0%------3.00V* 2/3 –-2v------155

     

    因为中间区分度太小,会出现电量在某格徘徊的情况,用阈值解决

    对于好一点的锂电池,一般在我们做产品测试时会在3.7V以后电压下降的很快,那么在短时间内放的电量就很少。相反不好的电池在4.2V到3.7V放电的时候,电压下降的很快,而在3.7V以后电压又下降的有很慢,这种电池是性能不好的一般容量也非常低。那么好的锂电池的放就是3.7V

    详情参考锂电池电压电量关系

     

    展开全文
  • 智能小车22:安装电压检测模块

    千次阅读 2017-08-29 08:20:17
    昨天设计了这个电压检测模块,有专家给我指了下这个电路的一些缺陷。基准电压本来就可能会不太稳定,所以用这个电压去测另一个电压会有误差。我暂时接受这个误差,继续下一步的试验,把这个电路与我的小车结合。 ...

    任何技术上的一点进步,都要经过十分的努力。


    设计电路对我来讲完全是一个新的技术。昨天设计了这个电压检测模块,有专家给我指了下这个电路的一些缺陷。基准电压本来就可能会不太稳定,所以用这个电压去测另一个电压会有误差。我暂时接受这个误差,继续下一步的试验,把这个电路与我的小车结合。

    前面的《智能小车九:不学电路图怎么造车》讲了我目前用的扩展板是arduino ProtoShield,这上面有两组灯的电路,我就选用这现成的吧。另外的检测电路我得自己焊接。焊接过程还是很曲折的,我是选择在充电接口这边开始焊接检测电路的,因为这里线路比较简单。但我错了,焊接好了拿到电脑上去检测怎么都不对,万能表显示也不对。后来才发现我这有个开关,在开机状态下,有一根线是不通电的。另外原来设计3号引脚也与以前的红外接口冲突了,所以我用了4号引脚。

    电压不足时,下面的灯会亮:

    复杂的背面线路:

    琐碎的小电线:


    现在总结一下,arduino uno的数字输入/输出口有2-13,共12个,现在已经用去了3(红外)、4(电压警告)、5(电机)、6(电机)、7(舵机)、9(电机)、10(电机),还剩下5个引脚。模拟的a0到a5用掉了a0,还剩5个引脚。

    这个小电路目前还没实机测量成功过,因为上了电路还没时间把他的电用完。如果这个小电路实验成功,这个特点一定能秒杀大多数玩具车,它们都没有哦。我们好多市面上的玩具为了节省成本,牺牲了多好的用户体验啊。有想检验一下我的车的同学可以加我微信,我们约一下时间,地点可能只能在北京了。

    展开全文
  • 24V低压检测电路 - 低压检测电压

    千次阅读 2018-06-20 17:26:02
    电压采样速率低和要求低时,左边电路图即可满足;当采样速率和精度要求比较高时,采用右边电路。Vin=24V低压检测电路,将24V转换到0-3V3之间,实测效果挺好的,电阻使用1%的精度。...


     当电压采样速率低和要求低时,左边电路图即可满足;当采样速率和精度要求比较高时,采用右边电路。

    Vin=24V低压检测电路,将24V转换到0-3V3之间,实测效果挺好的,电阻使用1%的精度。

    展开全文
  • 电压检测

    千次阅读 2016-10-18 16:49:36
    低功耗对于电子产品的重要性不言而喻,电表也不例外。在停电的时候,为了保证外部...NEC的UPD78F0527自带低电压检测电路。有两种方式检测电源是否低电压;①比较电源电压(VDD) 和检测电压( VLVI);②通过EXLVI脚
  • 这时候就不知道到底是那儿的问题,是线断了还是电压不够了。经过我很多次的经验得出,这是因为没电了。因为我每次这时候都会拿电压表去测一下,发现电池电压都在6v以下了。根据这个线索我设计了一个小电路来测电压。...
  • 单片机用AD测量电池电压的值

    万次阅读 2017-07-27 15:28:13
    单片机的引脚最大输入电压一般为3.3V或者5.0V,电流是25ma,40ma 而电池一般有3.3V-36V不等,电流也是好几A,超过5.0的电池一接到单片机 AD口,可能和三星手机一样。所有我们需要从电压电流2方面来入手考虑。 1...
  • 几个巧妙的电流检测电路

    万次阅读 2013-11-23 20:41:03
    在电源等设备中通常需要做电流检测或反馈,电流检测通常用串联采样电阻在通过放大器放大电阻上的电压的方法,如果要提高检测精度 这地方往往要用到比较 昂贵的仪表放大器,以为普通运放失调电压比较大。 下面介绍...
  • 过流检测与保护电路

    万次阅读 2018-06-24 12:11:50
    短路后过流检测与保护
  • 简单分压电路,检测电压

    千次阅读 2017-09-04 09:52:14
    输入任何三个值计算,然后按一下计算按钮。 电阻分流分压总电阻计算公式 ...设R1,R2并联,通过它们的电流为I1和I2 ...I1/(I1+I2)=R2/(R1+R2) I2/(I1+I2)=R1/...设R1,R2串联,通过它们的电压为U1和U2 I1=I2 U1/R1=U2/R2
  • 简便的电池电量测试设计方法

    万次阅读 2014-08-28 15:58:18
    2010-08-29 10:51:37| 分类: 方案资料|举报|字号 订阅 ...使用便携式电子产品,...电池电量检测技术在笔记本电脑中已经屡见不鲜,多数笔记本电脑都有电源管理的选项,提供不同的电源工作模式以及电池报警功
  • 开尔文四线检测(Kelvin Four-terminal sensing)也被称之为四端子检测(4T检测, 4T sensing)、四线检测或4点探针法,它是一种电阻抗测量技术,使用单独的对载电流和电压检测电极,相比传统的两个终端( 2T)传感...
  • Arduino的模拟信号输入——电压测试

    万次阅读 2018-04-12 16:09:39
    其中数字信号只有两个值,即高电压1和低电压0。数字信号输入和输出为pinModde(pin,mode); int value=digitalRead(pin);//输入该接口的信号 int value=digitalWrite(pin,HIGH);//输入高电平其中pin为引脚,可以在之前...
  • 电流检测电路

    万次阅读 2020-07-04 11:50:29
    参考: 1.一位年轻应用工程师的高端电流检测实验经历分享
  • 电压采集采样电路设计

    万次阅读 2019-10-18 16:32:08
    电压的采集是我们进行电路设计常常用到的,具体的采集类型上又分为直流采集和交流采集,将源电压通过一系列的电路设计,最终通过AD(数模转换芯片或单片机内部AD)读入MCU,并执行相应的决策,是我们大多设计的要求...
  • 模数转换器即A/D转换器,或简称ADC,通常是指一个将模拟信号转变为数字信号的电子元件。 先来看看N76E003 ADC工作方式 再看下相关寄存器,方便理解上图 ...
  • 过零检测电路原理与作用 可控整流

    万次阅读 2015-04-27 09:27:55
    原文地址:... 使用光耦 ...网友建议 电容代替那只47K的电阻,330欧电阻直接短路....电阻限流的缺点是过零脉冲的宽度与检测电压值相关.可以用一只0.1u/400v的无极性电
  • STM32的ADC参考电压,我们一般设置为3.3V,也就是说ADC采集到的外部电压最高也是3.3V,一般我们使用的电池可能要高于3.3v,这就需要对电池的电压进行降压处理。这就存在一个降压因子,也就是采集到的电压和电池的...
  • STC15内部ADC测电压

    千次阅读 2018-07-11 18:34:43
    STC15内部ADC测电压当VCC(基准电压)等于5V的时候,我们输入的是4v,那么ADC将4V转换的结果就是4/5*1024=819.2。这是一种比例关系。一般开发板的的基准电压采用的是3.3V....
1 2 3 4 5 ... 20
收藏数 35,496
精华内容 14,198
关键字:

电压检测