UART1串口的简单配置

写在前面的:这是我自己的学习记录,勿喷,大部分是自己对正点原子stm32f103实验的理解,但是代码是纯手敲,算是我自己的总结!! !

什么是USART

USATR:串行同步异步通信接口通用异步收发器(Universal Synchronous Asynchronous Receiver/Transmitter),一般用于全双串行行异步通信。所谓全双工,指的是收发可以同时进行;所谓串行,指的是数据传输按位一位一位进行。

补充:通信方式可分为串行通信和并行通信。

串行通信:按位一位一位进行传输
优点:占用引脚少
缺点:速度慢
并行通信:数据多位同时进行传输
优点:速度快
缺点:占用引脚多
常见的串行通信方式:
异步(不需要时钟线):UATR,A-WIRE
同步(必须要有同步时钟线):SPI ,IIC
至于单工,半双工,全双工心里有数就行了,不再单独列举

USART1的简单配置

//串口初始化函数
void usart_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	//使能串口时钟,其挂载在高速外围总线APB2上
	
	//GPIO初始化PA.9,PA.10作为串口的收发引脚
	//引脚的模式配置可查表
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//PA.9做发送引脚
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//PA.10做接收引脚
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//串口初始化
	USART_InitStructure.USART_BaudRate=115200;//设置波特率
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//模式选择为收发同时开启
	USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_StopBits=USART_StopBits_1;//一位停止位
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;//数据位字长8位
	USART_Init(USART1,&USART_InitStructure);
	
	//作为外设,必须对其使能
	USART_Cmd(USART1,ENABLE);//串口使能
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//配置串口中断类型并使能
	
	//中断向量初始化
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//选择中断通道为串口1中断
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//中断通道使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级:2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//子优先级:2
	NVIC_Init(&NVIC_InitStructure);
	
}

USART1的简单通信小协议

// An highlighted block
u16 usart_rx_state=0;
u8  usart_rx_buff[usart_rx_buff_len];
u16 len;
u16 t;
void USART1_IRQHandler(void)
{
	u8 data;
	
	if (USART_GetITStatus(USART1,USART_IT_RXNE))
	{
		data=USART_ReceiveData(USART1);
		if ((usart_rx_state&0x8000)==0)//上次接收以后,接收过程未完成
		{
			if (usart_rx_state&0x4000)//上次接收到了0x0d
			{
				if (data!=0x0a)//这次未接收到0x0a,接收过程错误
					usart_rx_state=0;//重新接收
				else 
					usart_rx_state|=0x8000;//这次接收到了0x0a,接收过程完成
			}
			else //上次未接收到0x0d
			 {
				 if (data==0x0d)
					 usart_rx_state|=0x4000;
				 else
				 {
					 usart_rx_buff[usart_rx_state&0X3FFF]=data;
					 usart_rx_state++;
					 if (usart_rx_state>200)
						 usart_rx_state=0;
				 }
			 }
		}
	}
}

在这个通信小协议中,定义了一个u16的usart_rx_state变量。usart_rx_state的低14位用来处理接收到的数据长度,第15位用来判断是否接收到了0x0d,如果接收到了,该位置1,第16位用来判断上一次是否接收到了0x0a,如果接收到了,且同时第15位已经置1,则该位置1,此时整个接收过程完成。
同时还定义了一个数据接收缓存数组u8 usart_rx_buff [ ],用来存放临时变量data中接收到的数据。数组的实际利用大小与usart_rx_state有关。

// An highlighted block
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_init();
	led_init();
	usart_init();
	led0=0,led1=1;
	
	while(1)
	{
		if (usart_rx_state&0x8000)
		{
			len=usart_rx_state&0x3fff;
			for (t=0;t<len;t++)
			{
				USART_SendData(USART1, usart_rx_buff[t]);
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
			}
			usart_rx_state=0;//准备接收下一次数据
		}
	}

}

在这段代码中,当接收过程完成以后,在先提取到接收到的数据长度,然后把缓存数组接收到的数据原原本本的发送出去。在发送过程中,需要使用到库函数USART_GetFlagStatus( )判断数组中一个元素发送是否完成,如果完成了,则进行下一个元素的发送操作,如果没有这句话,则会出现到意想不到的错误!!!

猜你喜欢

转载自blog.csdn.net/huaxhua4719/article/details/107657388