Stm32ADC和RS485

  • ADC

1、ADC概述

ADC, Analog-to-Digital Converter的缩写,指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。真实世界的模拟信号.例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射的数字形式。模/数转换器可以实现这个功能,在各种不同的产品中都可以找到它的身影。

模拟信号:是指用连续变化的物理量表示的信息,其信号的幅度,或频率,或相位随时间作连续变化,或在一段连续的时间间隔内,其代表信息的特征量可以在任意瞬间呈现为任意数值的信号。

数字信号:自变量是离散的、因变量也是离散的信号,这种信号的自变量用整数表示,因变量用有限数字中的一个数字来表示。在计算机中,数字信号的大小常用有限位的二进制数表示。

ADC转换步骤

1、采样:在时间轴上对信号数字化。也就是,按照固定的时间间隔抽取模拟信号的值,这样,采样后就可以使一个时间连续的信息波变为在时间上取值数目有限的离散信号。

2、量化:在幅度轴上对信号数字化。也就是,用有限个幅度值近似还原原来连续变化的幅度值,把模拟信号的连续幅度变为有限数量的有一定间隔的离散值。

3、编码:用二进制数表示每个采样的量化值(十进制数)。

2、STM32  ADC

STM32F407ZET6有3个ADC,每个ADC有12位、10位、8位和6位可选,每个ADC有16个外部通道。另外还有两个内部ADC源和VBAT通道挂在ADC1上。ADC具有独立模式、双重模式和三重模式,对于不同AD转换要求几乎都有合适的模式可选。ADC功能非常强大,具体的我们在功能框图中分析每个部分的功能。

ADC框架

规则通道

规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道,或者应该说我们用到的都是这个通道,没有什么特别要注意的可讲。

注入通道

注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。

规则序列

规则序列寄存器有3个,分别为SQR3、SQR2、SQR1。SQR3控制着规则序列中的第一个到第六个转换,对应的位为:SQ1[4:0]~SQ6[4:0],第一次转换的是位4:0 SQ1[4:0],如果通道16想第一次转换,那么在SQ1[4:0]写16即可。SQR2控制着规则序列中的第7到第12个转换,对应的位为:SQ7[4:0]~SQ12[4:0],如果通道1想第8个转换,则SQ8[4:0]写1即可。SQR1控制着规则序列中的第13到第16个转换,对应位为:SQ13[4:0]~SQ16[4:0],如果通道6想第10个转换,则SQ10[4:0]写6即可。具体使用多少个通道,由SQR1的位L[3:0]决定,最多16个通道。

3、ADC采集步骤过程

ADC采集需要添加的库函数文件:stm32f4xx_adc.c

  1. 理解电路原理图

可调电阻连接在PA5

ADC12_IN5

(2)、开启PA口时钟和ADC1时钟,设置PA5为模拟输入。

      RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  

      GPIO_Init();      

(3)、初始化ADC_CCR寄存器。

     ADC_CommonInit();

(4)、初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。

     void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);

(5)、使能ADC。

      ADC_Cmd(ADC1, ENABLE);

(6)、配置规则通道参数:

     ADC_RegularChannelConfig();

(7)、开启软件转换:ADC_SoftwareStartConv(ADC1);

(8)、等待转换完成,读取ADC值。

   ADC_GetConversionValue(ADC1);

  • RS485

1、RS485概述

485接口

485(一般称作RS485/EIA-485)是隶属于OSI模型物理层的电气特性规定为2线,半双工,多点通信的标准。它的电气特性和RS-232大不一样。用缆线两端的电压差值来表示传递信号。RS485仅仅规定了接受端和发送端的电气特性。它没有规定或推荐任何数据协议。

RS485推荐使用在点对点网络中,线型,总线型,不能是星型,环型网络。理想情况下RS485需要2个匹配电阻,其阻值要求等于传输电缆的特性阻抗(一般为120Ω)。没有特性阻抗的话,当所有的设备都静止或者没有能量的时候就会产生噪声,而且线移需要双端的电压差。没有终接电阻的话,会使得较快速的发送端产生多个数据信号的边缘,导致数据传输出错。

485推荐的连接方式:

简单地说,RS-232与RS-485的区别在于:传输方式不同、传输距离不同、RS-232 只允许一对一通信。

1、传输方式不同。 RS-232采取不平衡传输方式,即所谓单端通讯(一条线传输一位数据). 而RS485则采用平衡传输,即差分传输方式(两条线决定一位数据)。

2、传输距离不同。RS-232适合本地设备之间的通信,传输距离一般不超过20m。而RS-485的传输距离为几十米到上千米。

3、RS-232 只允许一对一通信,而RS-485 接口在总线上是允许连接多达128个收发器。

  1. RS485配置流程

RS485配置流程实际就是USART2的配置流程,这个流程可参考第六天USART1编程即可。在配置流程当中注意要配置RS485控制模式PG8为输出模式。

三、函数说明

/**

  * @brief  Initializes the ADCs peripherals according to the specified parameters

  *         in the ADC_CommonInitStruct.

  * @param  ADC_CommonInitStruct: pointer to an ADC_CommonInitTypeDef structure

  *         that contains the configuration information for  All ADCs peripherals.

  * @retval None

  */

void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);

函数说明:初始化ADC_CCR寄存器

返回值:无

ADC_CommonInitTypeDef结构体

ADC除了有ADC_InitTypeDef初始化结构体外,还有一个ADC_CommonInitTypeDef通用初始化结构体。ADC_CommonInitTypeDef结构体内容决定三个ADC共用的工作环境,比如模式选择、ADC时钟等等。

ADC_CommonInitTypeDef结构体也是定义在stm32_f4xx.h文件中,具体定义如下:

typedef struct {

uint32_t ADC_Mode; //ADC模式选择

uint32_t ADC_Prescaler; //ADC分频系数

uint32_t ADC_DMAAccessMode; //DMA模式配置

uint32_t ADC_TwoSamplingDelay; //采样延迟

} ADC_InitTypeDef;

ADC_ModeADC工作模式选择,有独立模式、双重模式以及三重模式。

/**

  * @brief  Initializes the ADCx peripheral according to the specified parameters

  *         in the ADC_InitStruct.

  * @note   This function is used to configure the global features of the ADC (

  *         Resolution and Data Alignment), however, the rest of the configuration

  *         parameters are specific to the regular channels group (scan mode

  *         activation, continuous mode activation, External trigger source and

  *         edge, number of conversion in the regular channels group sequencer).  

  * @param  ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.

  * @param  ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains

  *         the configuration information for the specified ADC peripheral.

  * @retval None

  */

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);

函数说明:初始化ADC_CCR寄存器

返回值:无

ADC_TypeDef* ADCx:哪个ADC外设

ADC_InitTypeDef结构体

ADC_InitTypeDef结构体定义在stm32f4xx_adc.h文件内,具体定义如下:

typedef struct {

uint32_t ADC_Resolution; //ADC分辨率选

FunctionalState ADC_ScanConvMode; //ADC扫描选择

FunctionalState ADC_ContinuousConvMode; //ADC连续转换模式选择

uint32_t ADC_ExternalTrigConvEdge; //ADC外部触发极性

uint32_t ADC_ExternalTrigConv; //ADC外部触发选择

uint32_t ADC_DataAlign; //输出数据对齐方式

uint8_t ADC_NbrOfChannel; //转换通道数目

} ADC_InitTypeDef;

ADC_Resolution:配置ADC的分辨率,可选的分辨率有12位、10位、8位和6位。分辨率越高,AD转换数据精度越高,转换时间也越长;分辨率越低,AD转换数据精度越低,转换时间也越短。

ScanConvMode:可选参数为ENABLEDISABLE,配置是否使用扫描。如果是单通道AD转换使用DISABLE,如果是多通道AD转换使用ENABLE

ADC_ContinuousConvMode:可选参数为ENABLEDISABLE,配置是启动自动连续转换还是单次转换。使用ENABLE配置为使能自动连续转换;使用DISABLE配置为单次转换,转换一次后停止需要手动控制才重新启动转换。

ADC_ExternalTrigConvEdge:外部触发极性选择,如果使用外部触发,可以选择触发的极性,可选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。

ADC_ExternalTrigConv:外部触发选择,图 01中列举了很多外部触发条件,可根据项目需求配置触发来源。实际上,我们一般使用软件自动触发。

ADC_DataAlign:转换结果数据对齐模式,可选右对齐ADC_DataAlign_Right或者左对齐ADC_DataAlign_Left。一般我们选择右对齐模式。

ADC_NbrOfChannelAD转换通道数目。

ADC_PrescalerADC时钟分频系数选择,ADC时钟是有PCLK2分频而来,分频系数决定ADC时钟频率,可选的分频系数为2468ADC最大时钟配置为36MHz

ADC_DMAAccessModeDMA模式设置,只有在双重或者三重模式才需要设置,可以设置三种模式,具体可参考参考手册说明。

ADC_TwoSamplingDelay:2个采样阶段之前的延迟,仅适用于双重或三重交错模式。

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

函数说明:配置规则通道

返回值:无

ADC_TypeDef* ADCx哪个ADC外设

uint8_t ADC_Channel通道

uint8_t Rank规则序列

ADC_SampleTimeADC采样间隔周期

  • 技术应用

烟雾报警器

电子称

 adc

#include "adc.h"

/**************************************
引脚说明:
可调电阻连接在PA5
ADC12_IN5
**************************************/
void Adc_PA5_Init(void)
{
	GPIO_InitTypeDef  		GPIO_InitStruct;
	ADC_CommonInitTypeDef 	ADC_CommonInitStruct;
	ADC_InitTypeDef			ADC_InitStruct;
	
	
	//(2)、开启PA口时钟和ADC1时钟,设置PA5为模拟输入。
	RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  
	
	
	GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_5;		//引脚9 10
	GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_AN;		//模拟模式
	GPIO_InitStruct.GPIO_PuPd	= GPIO_PuPd_NOPULL;	//无上下拉
	GPIO_Init(GPIOA,&GPIO_InitStruct);	 

	
	ADC_CommonInitStruct.ADC_Prescaler			= ADC_Prescaler_Div4;   		//APB2为84MHZ 84MHZ/4 = 21MHZ ADC的转化频率不能超过36MHZ 
	ADC_CommonInitStruct.ADC_Mode				= ADC_Mode_Independent; 		//独立模式 
	ADC_CommonInitStruct.ADC_DMAAccessMode		= ADC_DMAAccessMode_Disabled;	//不使用DMA
	ADC_CommonInitStruct.ADC_TwoSamplingDelay	= ADC_TwoSamplingDelay_10Cycles;//采样延迟
	//(3)、初始化ADC_CCR寄存器。
	ADC_CommonInit(&ADC_CommonInitStruct);
	
	
	ADC_InitStruct.ADC_Resolution			= ADC_Resolution_12b;			//12位分辨率
	ADC_InitStruct.ADC_DataAlign			= ADC_DataAlign_Right;			//数据右对齐
	ADC_InitStruct.ADC_ContinuousConvMode	= DISABLE;						//连续转换
	//ADC_InitStruct.ADC_ExternalTrigConv		=							//不填写,表示默认使用软件触发
	ADC_InitStruct.ADC_ExternalTrigConvEdge	= ADC_ExternalTrigConvEdge_None; //无边沿触发
	ADC_InitStruct.ADC_NbrOfConversion		= 1;							//ADC转换通道数目
	ADC_InitStruct.ADC_ScanConvMode			= DISABLE;						//不扫描
	//(4)、初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
	ADC_Init(ADC1, &ADC_InitStruct);
	
	
	
	//(5)、使能ADC。
	ADC_Cmd(ADC1, ENABLE);
	
	//(6)、配置规则通道参数:
	ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_15Cycles);

}


u16 Get_Adc_Value(void)
{
	u16 value;
	
	//开启软件转换:
	ADC_SoftwareStartConv(ADC1);
	//等待转换结束
	while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
	//获取规则寄存器的值
	value = ADC_GetConversionValue(ADC1);
	
	return value;
}
#ifndef __ADC_H
#define __ADC_H

#include "stm32f4xx.h"



void Adc_PA5_Init(void);
u16 Get_Adc_Value(void);

#endif
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "sys.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"
#include "iic.h"
#include "adc.h"

u8  buffer[64] = {0};
u8  rx_buffer[64] = {0};
u8  count = 0, rx_i = 0;
u8  rx_flag = 0; //接受标志位,rx_flag = 表示数据帧完毕


void USART1_IRQHandler(void)
{
	


	//判断接收标志位是否为1
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		//清空接受标志位
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);	
		//接受数据 
		buffer[count++] = USART_ReceiveData(USART1);
		//判断数据是否为':',如果是':'数据帧结束
		if(buffer[count-1] == ':')
		{
			//数据赋值到rx_buffer,并过滤帧尾
			for(rx_i=0; rx_i<(count-1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
		
			//清空数组
			memset(buffer, 0, sizeof(buffer));
			
			//标志位置1
			rx_flag = 1;
			//下一帧数据从buffer[0]开始接受
			count = 0; 
					
		
		}
		
	}
}




void USART2_IRQHandler(void)
{
	
	u8 data;

	//判断接收标志位是否为1
	if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
	{
		//清空接受标志位
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);	
		//接受数据 
		buffer[count++] = USART_ReceiveData(USART2);
		//判断数据是否为':',如果是':'数据帧结束
		if(buffer[count-1] == ':')
		{
			//数据赋值到rx_buffer,并过滤帧尾
			for(rx_i=0; rx_i<(count-1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
		
			//清空数组
			memset(buffer, 0, sizeof(buffer));
			
			//标志位置1
			rx_flag = 1;
			//下一帧数据从buffer[0]开始接受
			count = 0; 
					
		}
		
	}


}


void USART3_IRQHandler(void)
{
	
	u8 data;

	//判断接收标志位是否为1
	if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
	{
		//清空接受标志位
		USART_ClearITPendingBit(USART3, USART_IT_RXNE);	
		//接受数据 
		buffer[count++] = USART_ReceiveData(USART3);
		//判断数据是否为':',如果是':'数据帧结束
		if(buffer[count-1] == ':')
		{
			//数据赋值到rx_buffer,并过滤帧尾
			for(rx_i=0; rx_i<(count-1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
		
			//清空数组
			memset(buffer, 0, sizeof(buffer));
			
			//标志位置1
			rx_flag = 1;
			//下一帧数据从buffer[0]开始接受
			count = 0; 
					
		}
		
	}


}




int main(void)
{

	u16 	adc_value;
	float 	f_value;
	
	//设置NVIC分组(一个工程只能设置一个分组) 
	//第二分组;抢占优先组取值范围:0~3 响应先组取值范围:0~3
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Led_Init();
	Delay_Init();
	Usart1_Init(115200);
	Adc_PA5_Init();
	
	
	while(1)
	{
		
		
		adc_value = Get_Adc_Value();
		
		f_value = (adc_value/4095.0)*3.3;
		
		printf("采集的数字值:%d\r\n", adc_value);
		printf("采集电压值:%f\r\n", f_value);
		//这里的循环相当应用程序的时间
		delay_s(1);


	}
}

rs485_rx

#include "rs485.h"

/*****************************************
引脚说明:

PA2 -- U2_TX
PA3 -- U2_RX

RS485_RE -- PG8
****************************************/

void Rs485_Init(int MYBaudRate)
{

	
	GPIO_InitTypeDef  GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
	
	
	//使能 USART2 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	//B.  使用的是串口 1,串口 1 对应着芯片引脚 PA2,PA3 需要使能PA的时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); 
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE); 
	//2)  设置引脚复用器映射
	//PA2 复用为 USART2
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); 
	//PA3 复用为 USART3
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);

	
	
	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2 与 GPIOA3
	GPIO_InitStruct.GPIO_Mode 	= GPIO_Mode_AF;				//配置IO口复用功能
	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz; 		//速度 50MHz
	GPIO_InitStruct.GPIO_OType 	= GPIO_OType_PP; 			//推挽复用输出
	GPIO_InitStruct.GPIO_PuPd 	= GPIO_PuPd_UP; 			//上拉
	//初始化 PA2 PA3
	GPIO_Init(GPIOA,&GPIO_InitStruct); 
	
	
	
	USART_InitStruct.USART_BaudRate 	= MYBaudRate;					//波特率 115200;
	USART_InitStruct.USART_WordLength 	= USART_WordLength_8b;		//字长为 8 位数据格式
	USART_InitStruct.USART_StopBits 	= USART_StopBits_1;			//一个停止位
	USART_InitStruct.USART_Parity 		= USART_Parity_No;			//无奇偶校验位
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件控制流
	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	//初始化串口
	USART_Init(USART2, &USART_InitStruct); 
	
	
	NVIC_InitStruct.NVIC_IRQChannel 					= USART2_IRQn;  //中断通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority	=3;				//抢占优先级 3
	NVIC_InitStruct.NVIC_IRQChannelSubPriority 			=3;  			//响应优先级 3
	NVIC_InitStruct.NVIC_IRQChannelCmd 					= ENABLE; 		//IRQ 通道使能
	//根据指定的参数初始化 VIC 寄存器
	NVIC_Init(&NVIC_InitStruct);  
	
	//接收中断
	USART_ITConfig(USART2, USART_IT_RXNE ,ENABLE);	
	
	//中断使能
	USART_Cmd(USART2, ENABLE);	
	

	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_8; 				//GPIOG8
	GPIO_InitStruct.GPIO_Mode 	= GPIO_Mode_OUT;			//配置IO口输出模式
	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz; 		//速度 50MHz
	GPIO_InitStruct.GPIO_OType 	= GPIO_OType_PP; 			//推挽复用输出
	GPIO_InitStruct.GPIO_PuPd 	= GPIO_PuPd_UP; 			//上拉
	GPIO_Init(GPIOG,&GPIO_InitStruct); 


}

void Rs485_Send(u8 *data, u16 len)
{
	u16 i;
	
	for(i=0; i<len; i++)
	{
		USART_SendData(USART2,*(data+i));  //通过串口发送数据
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);  
	
	
	}
	
	

	

}









#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "string.h"
#include "sys.h"
#include "sr04.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"
#include "rtc.h"
#include "adc.h"
#include "dac.h"
#include "iic.h"
#include "spiflash.h"
#include "flash.h"
#include "rs485.h"

u8 rx_flag = 0;  //rx_flag = 1表示接受数据完成
u8 data = 0;    


u8 buffer[32] = {0};
u8 rx_buffer[32] = {0};
u8 rx_i = 0;
u8 rx_count = 0;



//定时器中断服务函数
void USART1_IRQHandler(void)
{
	
	
	//判断中断标志位是否置为1
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		//清除中断标志位
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
		//接收数据
		buffer[rx_count++] = USART_ReceiveData(USART1);

		//判断是否接受到帧尾
		if(buffer[rx_count - 1] == ':')
		{
			//过滤帧尾,并将数据存储到rx_buffer当中
			for(rx_i = 0; rx_i < (rx_count - 1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
			
			memset(buffer,0, sizeof(buffer));
			
			rx_count = 0;  //下一帧数据从头开始
			rx_flag = 1;
		}
	
	}

}


void USART2_IRQHandler(void)
{
	
	
	//判断中断标志位是否置为1
	if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
	{
		//清除中断标志位
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
		//接收数据
		buffer[rx_count++] = USART_ReceiveData(USART2);

		//判断是否接受到帧尾
		if(buffer[rx_count - 1] == ':')
		{
			//过滤帧尾,并将数据存储到rx_buffer当中
			for(rx_i = 0; rx_i < (rx_count - 1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
			
			memset(buffer,0, sizeof(buffer));
			
			rx_count = 0;  //下一帧数据从头开始
			rx_flag = 1;
		}
	
	}

}




void Usart2_SendStr(u8 *buff, u8 len)
{
	u8 i;
	
	for(i=0; i<len; i++)
	{
		USART_SendData(USART2,buff[i]);  //通过串口发送数据
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);   
	}

	
}



int main(void)
{
	u16 id;

	
	//设置NVIC分组(一个工程只能有一个分组) 抢占优先级范围:0~3  响应优先级范围:0~3 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Led_Init();
	Key_Init();
	Delay_Init();
	Usart1_Init(115200);
	
	Rs485_Init(9600);
	//接受端
	PGout(8) = 0;

	
	while(1)
	{

		if(rx_flag == 1)
		{
			if(strcmp(rx_buffer,"H6CL11") == 0)
			{
				LED0_ON;
			}
			
			if(strcmp(rx_buffer,"H6CL10") == 0)
			{
				LED0_OFF;
			}			
			
			memset(rx_buffer,0, sizeof(rx_buffer));
			
			rx_flag = 0;
		}	

	}
	
	return 0;
}

rs485_tx

#include "rs485.h"

/*****************************************
引脚说明:

PA2 -- U2_TX
PA3 -- U2_RX

RS485_RE -- PG8
****************************************/

void Rs485_Init(int MYBaudRate)
{

	
	GPIO_InitTypeDef  GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
	
	
	//使能 USART2 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	//B.  使用的是串口 1,串口 1 对应着芯片引脚 PA2,PA3 需要使能PA的时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); 

	//2)  设置引脚复用器映射
	//PA2 复用为 USART2
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); 
	//PA3 复用为 USART3
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);

	
	
	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2 与 GPIOA3
	GPIO_InitStruct.GPIO_Mode 	= GPIO_Mode_AF;				//配置IO口复用功能
	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz; 		//速度 50MHz
	GPIO_InitStruct.GPIO_OType 	= GPIO_OType_PP; 			//推挽复用输出
	GPIO_InitStruct.GPIO_PuPd 	= GPIO_PuPd_UP; 			//上拉
	//初始化 PA2 PA3
	GPIO_Init(GPIOA,&GPIO_InitStruct); 
	
	
	
	USART_InitStruct.USART_BaudRate 	= MYBaudRate;					//波特率 115200;
	USART_InitStruct.USART_WordLength 	= USART_WordLength_8b;		//字长为 8 位数据格式
	USART_InitStruct.USART_StopBits 	= USART_StopBits_1;			//一个停止位
	USART_InitStruct.USART_Parity 		= USART_Parity_No;			//无奇偶校验位
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件控制流
	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	//初始化串口
	USART_Init(USART2, &USART_InitStruct); 
	
	
	NVIC_InitStruct.NVIC_IRQChannel 					= USART2_IRQn;  //中断通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority	=3;				//抢占优先级 3
	NVIC_InitStruct.NVIC_IRQChannelSubPriority 			=3;  			//响应优先级 3
	NVIC_InitStruct.NVIC_IRQChannelCmd 					= ENABLE; 		//IRQ 通道使能
	//根据指定的参数初始化 VIC 寄存器
	NVIC_Init(&NVIC_InitStruct);  
	
	//接收中断
	USART_ITConfig(USART2, USART_IT_RXNE ,ENABLE);	
	
	//中断使能
	USART_Cmd(USART2, ENABLE);	
	

	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_8; 				//GPIOG8
	GPIO_InitStruct.GPIO_Mode 	= GPIO_Mode_OUT;			//配置IO口输出模式
	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz; 		//速度 50MHz
	GPIO_InitStruct.GPIO_OType 	= GPIO_OType_PP; 			//推挽复用输出
	GPIO_InitStruct.GPIO_PuPd 	= GPIO_PuPd_UP; 			//上拉
	GPIO_Init(GPIOG,&GPIO_InitStruct); 


}

void Rs485_Send(u8 *data, u16 len)
{
	u16 i;
	
	for(i=0; i<len; i++)
	{
		USART_SendData(USART2,*(data+i));  //通过串口发送数据
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);  
	
	
	}
}









#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"
#include "usart.h"
#include "string.h"
#include "sys.h"
#include "sr04.h"
#include "dht11.h"
#include "infrared.h"
#include "iwdg.h"
#include "rtc.h"
#include "adc.h"
#include "dac.h"
#include "iic.h"
#include "spiflash.h"
#include "flash.h"
#include "rs485.h"

u8 rx_flag = 0;  //rx_flag = 1表示接受数据完成
u8 data = 0;    


u8 buffer[32] = {0};
u8 rx_buffer[32] = {0};
u8 rx_i = 0;
u8 rx_count = 0;



//定时器中断服务函数
void USART1_IRQHandler(void)
{
	
	
	//判断中断标志位是否置为1
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		//清除中断标志位
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
		//接收数据
		buffer[rx_count++] = USART_ReceiveData(USART1);

		//判断是否接受到帧尾
		if(buffer[rx_count - 1] == ':')
		{
			//过滤帧尾,并将数据存储到rx_buffer当中
			for(rx_i = 0; rx_i < (rx_count - 1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
			
			memset(buffer,0, sizeof(buffer));
			
			rx_count = 0;  //下一帧数据从头开始
			rx_flag = 1;
		}
	
	}

}

void USART2_IRQHandler(void)
{
	
	//判断中断标志位是否置为1
	if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
	{
		//清除中断标志位
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
		//接收数据
		buffer[rx_count++] = USART_ReceiveData(USART2);

		//判断是否接受到帧尾
		if(buffer[rx_count - 1] == ':')
		{
			//过滤帧尾,并将数据存储到rx_buffer当中
			for(rx_i = 0; rx_i < (rx_count - 1); rx_i++)
			{
				rx_buffer[rx_i] = buffer[rx_i];
			}
			
			memset(buffer,0, sizeof(buffer));
			
			rx_count = 0;  //下一帧数据从头开始
			rx_flag = 1;
		}
	
	}

}


void Usart2_SendStr(u8 *buff, u8 len)
{
	u8 i;
	
	for(i=0; i<len; i++)
	{
		USART_SendData(USART2,*(buff+i));  //通过串口发送数据
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);   
//		USART_SendData(USART1,buff[i]);  //通过串口发送数据
//		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); 		
	}

	
}



int main(void)
{
	u16 id;
	u8 write_buff[27] = "ABCDEFGHI18LMNOPQRSTUVWXYZ";
	u8 read_buff[27] = {0};
	
	//设置NVIC分组(一个工程只能有一个分组) 抢占优先级范围:0~3  响应优先级范围:0~3 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Led_Init();
	Key_Init();
	Delay_Init();
	Usart1_Init(115200);
	
	Rs485_Init(9600);
	//发送端
	PGout(8) = 1;
	printf("test\n");
	
	while(1)
	{

		//判断按键是否按下
		if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET)
		{
			delay_ms(15);  //延时消抖
			//判断按键是否按下
			if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET)
			{
				while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET); //等待按键松开
				Usart2_SendStr("H6CL11:", 7);

			}		
		}
		
		
		if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) == Bit_RESET)
		{
			delay_ms(15);  //延时消抖
			//判断按键是否按下
			if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) == Bit_RESET)
			{
				//按键按下要处理的事件
				while(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) == Bit_RESET); //等待按键松开
				Usart2_SendStr("H6CL10:", 7);

				
			}		
		}		

	}
	
	return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值