利用ADC实现光敏电阻的数字量采集并通过串口输出

点击查看代码
/**
   ******************************************************************************
   * @file    main.c 
   * @author  
   * @version 
   * @date    2024/06/28
   * @brief   实现利用串口完整的接收蓝牙发送过来的数据,并把数据存储在数据缓冲区,
						  把数组转发给电脑
						  
							BEEP_ON  0x01 启动
							BEEP_OFF 0x00 关闭
							
   ******************************************************************************
**/

#include "stm32f4xx.h"  //必须包含
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define  BUFSIZE  128

uint8_t  recvbuf[BUFSIZE] ={0};  //用于存储串口收到的数
uint32_t recvcnt = 0;						 //用于作为数组的计数器

//延时微秒 注意:Systick是24bit的递减计数器  约等于798915us,所以参数不可以超过这个值
void delay_us(u32 nus)
{
	SysTick->CTRL = 0; 						 // 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
	SysTick->LOAD = (nus * 21) - 1;// 指的是计数次数,定时时间 = 计数次数 * 计数周期
	SysTick->VAL  = 0; 						 // 清除当前数值寄存器的值
	SysTick->CTRL = 1; 						 // 开启了定时器,并且定时器的时钟源选择了21MHZ--> 计数周期 = 1/21us
	while ((SysTick->CTRL & 0x00010000)==0);//等待延时时间到达
	SysTick->CTRL = 0; 						 // 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器

}

//延时毫秒 注意:Systick是24bit的递减计数器  约等于798ms,所以参数不可以超过这个值
void delay_ms(u32 nms)
{
	SysTick->CTRL = 0; 						 			// 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
	SysTick->LOAD = (nms * 21*1000) - 1;// 指的是计数次数,定时时间 = 计数次数 * 计数周期
	SysTick->VAL  = 0; 						 			// 清除当前数值寄存器的值
	SysTick->CTRL = 1; 						 			// 开启了定时器,并且定时器的时钟源选择了21MHZ--> 计数周期 = 1/21us
	while ((SysTick->CTRL & 0x00010000)==0);//等待延时时间到达
	SysTick->CTRL = 0; 						 			// 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
}


//前台程序就是中断服务程序,该程序是不需要手动调用的,当中断触发之后CPU会自动跳转过来执行该函数
void USART2_IRQHandler(void)
{
	
  //判断中断是否发生
  if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
  {   
		//从USART2中接收一个字节
		recvbuf[recvcnt++] = USART_ReceiveData(USART2);  //一次只能接收一个字节   
		
		//为了提高程序的可靠性,应该对数据大小进行分析
		if(recvcnt >= BUFSIZE)
		{
			  memset(recvbuf,0,BUFSIZE); //清空数组
			  recvcnt = 0;
		}
  }
}



void BEEP_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//打开了GPIO端口时钟  PF8
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_8;
	GPIO_Init(GPIOF, &GPIO_InitStructure);

}



void USART2_Config(u32 baud)
{
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//打开了GPIO端口时钟  PA2和PA3
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	//打开USART2的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//选择GPIO引脚的复用功能
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2 , GPIO_AF_USART2);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3 , GPIO_AF_USART2);
	
	//配置GPIO引脚 注意:复用模式
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_2|GPIO_Pin_3;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	//配置串口参数+对串口初始化
	USART_InitStructure.USART_BaudRate = baud;																			//波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;											//数据位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;													//停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;															//无校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无流控
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;									//收发模式
	USART_Init(USART2, &USART_InitStructure);

	//配置NVIC参数 + 对NVIC初始化
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	//选择USART2的中断源,接收到数据则触发中断
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	
	//打开串口
	USART_Cmd(USART2, ENABLE);
}


//利用串口发送一个字符串
void  USART2_SendString(const char *str)
{
	while(*str)
	{
		 USART_SendData(USART2,*str++);
		 while( USART_GetFlagStatus(USART2,USART_FLAG_TXE) == RESET );		
	}
}

//前台程序就是中断服务程序,该程序是不需要手动调用的,当中断触发之后CPU会自动跳转过来执行该函数
void USART1_IRQHandler(void)
{
	uint8_t data;
  //判断中断是否发生
  if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  {   
		//从USART1中接收一个字节
		data = USART_ReceiveData(USART1);  //一次只能接收一个字节   
		
		//把接收到的数据转发出去
		USART_SendData(USART1,data);
  }
}
void USART1_Config(u32 baud)
{
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//打开了GPIO端口时钟  PA9和PA10
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	//打开USART1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	//选择GPIO引脚的复用功能
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9 , GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
	
	//配置GPIO引脚 注意:复用模式
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_9|GPIO_Pin_10;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	//配置串口参数+对串口初始化
	USART_InitStructure.USART_BaudRate = baud;																			//波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;											//数据位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;													//停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;															//无校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无流控
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;									//收发模式
	USART_Init(USART1, &USART_InitStructure);

	//配置NVIC参数 + 对NVIC初始化
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	//选择USART1的中断源,接收到数据则触发中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	//打开串口
	USART_Cmd(USART1, ENABLE);
}

//利用串口发送一个字符串
void  USART1_SendString(const char *str)
{
	while(*str)
	{
		 USART_SendData(USART1,*str++);
		 while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET );		
	}
}

void LIGHT_Config(void)
{
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;

	//1.打开时钟  PF7 -- ADC3_IN5
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
	
	//2.配置引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
	GPIO_Init(GPIOF, &GPIO_InitStructure);

	//3.配置ADC参数
	ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;										//独立模式
	ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
	ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;		  //不使用DMA
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
	ADC_CommonInit(&ADC_CommonInitStructure);
	
	//4.配置ADC的通道
	ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;											//转换精度  0~4095
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;																//不扫描
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;													//不连续
	ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //不使用外部触发
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;											//右对齐
	ADC_InitStructure.ADC_NbrOfConversion = 1;																	//转换数量
	ADC_Init(ADC3, &ADC_InitStructure);
	
	//5.选择ADC的通道
	ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);
	
	//6.使能ADC3
	ADC_Cmd(ADC3, ENABLE);
}



int main()
{
	uint16_t val = 0;
	uint8_t buf[128] = {0};
	
	//1.硬件的初始化
	USART1_Config(9600);  //电脑
	LIGHT_Config();
	
	while(1)
	{
		//开启ADC的转换
		ADC_SoftwareStartConv(ADC3);
		
		//等待转换完成之后才可以读取寄存器的值
		while( ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC) == RESET );
		
		//获取转换结果并转发给电脑
		val = ADC_GetConversionValue(ADC3);
		
		//输出结果  0 ~ 4095
		sprintf((char *)buf,"val = %d\r\n",val);  //格式化转换
		USART1_SendString((char *)buf);
		
		delay_ms(500);
	}
}





posted @ 2025-08-30 12:26  w1888  阅读(30)  评论(0)    收藏  举报