串口的相关概念自行百度理解,在上节的红外载波调制已经介绍过I/O的复用功能,使能I/O时钟,同时把GPIO模式设置为复用功能对应的模式,使能引脚复用,串口配置在此基础上对串口参数做初始化配置,包括比特率、停止位等参数,设置完接下来就是使能串口,同时如果开启了串口中断,还需要初始化NVIC设置中断优先级别,最后编写中断服务函数。
串口配置
void USART1_Init()
{
//Structure Init
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //使能GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART的时钟
/* USART1的端口配置 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); //配置PA9成第二功能引脚 TX
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); //配置PA10成第二功能引脚 RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //GPIO模式为复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART1的基本配置 */
USART_InitStructure.USART_BaudRate = USART1_BaudRate; //波特率,可以定义成宏或者是做传参给到,记得跟串口接收端统一波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位
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); //初始化串口
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //使能接收中断
USART_Cmd(USART1, ENABLE); //使能USART1
/* USART1的NVIC配置 */
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0x02;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStruct); //中断优先级初始化
}
在这需要注意一点,如果是初次接触串口配置的新手,在初始化函数中使能过串口中断的话,一定要编写串口中断服务函数,不然虽然程序可以编译过去,但是运行代码的时候会跑到堆栈里面去然后跑死,而且芯片也不能再烧录程序,把MCU吹下来再换个新的才能继续烧录,在下第一次烧坏MCU后,排查代码串口初始化配置,还有硬件方面,都没配置错,直到连续烧了7片MCU接近奔溃把中断服务函数补回去试过后才不会跑死。因为也是第一次使用M0,而且我串口只需要做数据发送,不需要做接收处理,所以没写串口中断服务函数,只能因为一条使能串口中断。希望初学者不用犯同样的错误。
下面是串口中断服务函数
USART1_IRQHandler函数
void USART1_IRQHandler(void)
函数是串口1的中断响应函数,当串口1发生了相应的中断后就会跳转到该函数执行。中断响应函数的名字是不能随便定义的,一般都遵循MDK定义的函数名。这些函数名字在启动文件 startup_stm32f030.s 文件中可以找到。
函数体里面通过函数:
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
判断是否接收中断,如果是串口接收中断,则读取串口接收到的数据:
Res = USART_ReceiveData(USART1);
// (USART1->DR) //读取接收到的数据
读到数据后接下来就对数据进行分析,大概理解到这就行了,接着是中断服务函数~
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){}
}
用不到接收中断的话 if()
里面留空就行了,方便后面需要用到接收中断。
串口数据发送
可以在 stm32f0xx_usart.c
文件中看到函数定义:
/**
* @brief Transmits single data through the USARTx peripheral.
* @param USARTx: where x can be from 1 to 8 to select the USART peripheral.
* @note USART3 and USART4 are available only for STM32F072 and STM32F091 devices.
* @note USART5, USART6, USART7 and USART8 are available only for STM32F091 devices.
* @note USART2 is not available for STM32F031 devices.
* @param Data: the data to transmit.
* @retval None
*/
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
/* Transmit Data */
USARTx->TDR = (Data & (uint16_t)0x01FF);
}
参数为串口名,需要传输的数据,直接调用
USART_SendData(USART1,(uint16_t)keyStatus);
因为怕数据转换发送错误,我在前面加了强制16位转换,看USART_SendDat
函数定义就清楚了。