写在前面的:这是我自己的学习记录,勿喷,大部分是自己对正点原子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( )判断数组中一个元素发送是否完成,如果完成了,则进行下一个元素的发送操作,如果没有这句话,则会出现到意想不到的错误!!!