stm32f10x串口通讯
文章目录
基于stm32f103zet6
串口发送使用DMA发送
大致说明
USART_Rx_Sbuffer二维数组 -> 串口接收缓存区
一共3行 Rx_SbufferSize 列 ,Rx_SbufferSize由宏定义。
0,1,2行分别是串口1,2,3的接收缓存,由串口中断将接收到的数据存入对应的缓存区中。
可以使用Usart_Read()函数来读取缓存区的内容,(返回的是对应缓存区的首地址),**特别注意! 每行第1个元素表示的式该行接收到的数据个数,并不是接收到的数据!**读取到内容(或帧)后,可以使用USART_Push()和USART_Clear()来清除缓存区。
USART_Tx_Sbuffer二维数组 -> 串口DMA发送缓存区
一共3行 Tx_SbufferSize 列,Tx_SbufferSize 由宏定义。
0,1,2行是表示串口1,2,3的发送缓存,由串口发送函数Usart_Send()将要发送的数据存入对应的缓存区中。特别注意! 每行第1个元素表示的式该行要发送的数据的个数,并不是要发送的数据,同时具有DMA在忙标志位的作用,在忙标志由DMA中断清除
bsp_usart.c
#include "bsp_usart.h"
void BSP_Usart_Init(void)
{
USART_GPIO_Init(); //串口GPIO初始化
USART_Config(); //串口配置
USART_NVIC_Config(); //串口接收中断配置
USART_DMA_Config(); //串口发送DMA和DMA中断配置
//使能串口
for(uint8_t temp=0;temp<3;temp++)
USART_Cmd(Target_Usart[temp],ENABLE);
}
void USART_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_2;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_3;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOB,&GPIO_InitStruct);
}
void USART_Config(void)
{
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
for(uint8_t temp=0;temp<3;temp++)
USART_Init(Target_Usart[temp],&USART_InitStruct);
}
void USART_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
NVIC_Init(&NVIC_InitStruct);
//设置串口中断类型
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
//清除中断标志位
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
USART_ClearITPendingBit(USART3,USART_IT_RXNE);
}
void USART_DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE);
DMA_InitStruct.DMA_BufferSize = 0;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
//设置DMA的地址
for(uint8_t temp=0;temp<3;temp++)
{
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&Target_Usart[temp]->DR;
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&USART_Tx_Sbuffer[temp][1];
DMA_Init(TargetDMA_Channel[temp],&DMA_InitStruct); //初始化DMA
USART_DMACmd(Target_Usart[temp],USART_DMAReq_Tx,ENABLE); //设置串口DMA类型(发送)
DMA_ClearFlag(DMA1_FLAG_TC1); //清除标志位
}
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 8;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel7_IRQn;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_Init(&NVIC_InitStruct);
//使能DMA通道
for(uint8_t temp=0;temp<3;temp++)
DMA_ITConfig(TargetDMA_Channel[temp],DMA_IT_TC,ENABLE);
}
void USART_Push(uint8_t USARTx,uint8_t len)
{
if(USART_Rx_Sbuffer[USARTx-1][0] > len)
{
uint8_t temp;
USART_Rx_Sbuffer[USARTx-1][0] -= len;
for(temp=0; temp<USART_Rx_Sbuffer[USARTx-1][0] ; temp++)
USART_Rx_Sbuffer[USARTx-1][temp+1] = USART_Rx_Sbuffer[USARTx-1][temp+1+len];
return;
}
USART_Clear(USARTx);
}
void USART_Clear(uint8_t USARTx)
{
USART_Rx_Sbuffer[USARTx-1][0] = 0;
}
uint8_t Usart_Send(uint8_t USARTx,uint8_t *dat,uint8_t len)
{
if(Usart_BusyCheck(USARTx)==0)
{
uint8_t temp;
USART_Tx_Sbuffer[USARTx-1][0] = len;
for(temp=0;temp<len;temp++)
USART_Tx_Sbuffer[USARTx-1][temp+1] = *(dat+temp);
TargetDMA_Channel[USARTx-1]->CNDTR = len;
TargetDMA_Channel[USARTx-1]->CCR |= DMA_CCR1_EN;
return 0;
}
return 1;
}
uint8_t Usart_BusyCheck(uint8_t USARTx)
{
if(USART_Tx_Sbuffer[USARTx-1][0] != 0)
return 1;
else
return 0;
}
uint8_t*Usart_Read(uint8_t USARTx)
{
return USART_Rx_Sbuffer[USARTx-1];
}
void Rx_SbufferInput(uint8_t USARTx,uint8_t dat)
{
//判断缓存区是否满载
if(USART_Rx_Sbuffer[USARTx-1][0] < Rx_SbufferSize-1)
{
USART_Rx_Sbuffer[USARTx-1][ USART_Rx_Sbuffer[USARTx-1][0]+1 ] = dat;
USART_Rx_Sbuffer[USARTx-1][0]++;
}else
USART_Rx_Sbuffer[USARTx-1][0] = Rx_SbufferSize;
}
void Tx_Flag_Clear(uint8_t USARTx)
{
USART_Tx_Sbuffer[USARTx-1][0] = 0;
}
int fputc (int c, FILE *fp)
{
while(Usart_BusyCheck(1)); //防止和DMA冲突
USART_SendData(USART1,c);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
return c;
}
bsp_usart.h
#ifndef _BSP_USART_H_
#define _BSP_USART_H_
#include "stm32f10x.h"
#include <stdio.h>
//定义缓存大小
#define Rx_SbufferSize 64
#define Tx_SbufferSize 64
//每行第一个元素表示该缓存区存放的数据个数
static uint8_t USART_Rx_Sbuffer[3][Rx_SbufferSize] = {{0},{0},{0}};
static uint8_t USART_Tx_Sbuffer[3][Tx_SbufferSize] = {{0},{0},{0}};
static USART_TypeDef* Target_Usart[3] = {USART1,USART2,USART3};
static DMA_Channel_TypeDef* TargetDMA_Channel[3] = {DMA1_Channel4,DMA1_Channel7,DMA1_Channel2};
//初始化
void BSP_Usart_Init(void);
void USART_GPIO_Init(void);
void USART_Config(void);
void USART_NVIC_Config(void);
void USART_DMA_Config(void);
//发送&接收
uint8_t*Usart_Read(uint8_t USARTx);
uint8_t Usart_Send(uint8_t USARTx,uint8_t *dat,uint8_t len);
uint8_t Usart_BusyCheck(uint8_t USARTx); //检查DMA是否在忙
void USART_Clear(uint8_t USARTx); //清除接收缓存区
void USART_Push(uint8_t USARTx,uint8_t len); //将缓存区前移len个字节
void Rx_SbufferInput(uint8_t USARTx,uint8_t dat); //将接收到的dat载入对应缓冲区
void Tx_Flag_Clear(uint8_t USARTx); //清除DMA发送在忙(软件)
//printf()重定向
int fputc (int c, FILE *fp);
#endif
isr.c
#include "isr.h"
#include "bsp_usart.h"
//extern SemaphoreHandle_t Usart_Rx_Flag;
void USART1_IRQHandler(void)
{
//BaseType_t temp = pdFALSE;
if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
{
Rx_SbufferInput(1,USART_ReceiveData(USART1));
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
{
Rx_SbufferInput(2,USART_ReceiveData(USART2));
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
}
}
void USART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3,USART_IT_RXNE) == SET)
{
Rx_SbufferInput(3,USART_ReceiveData(USART3));
USART_ClearITPendingBit(USART3,USART_IT_RXNE);
}
}
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC4) == SET)
{
Tx_Flag_Clear(1);
TargetDMA_Channel[0]->CCR &= (uint16_t)(~DMA_CCR1_EN);
DMA_ClearITPendingBit(DMA1_IT_TC4);
}
}
void DMA1_Channel7_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC7) == SET)
{
Tx_Flag_Clear(2);
TargetDMA_Channel[1]->CCR &= (uint16_t)(~DMA_CCR1_EN);
DMA_ClearITPendingBit(DMA1_IT_TC7);
}
}
void DMA1_Channel2_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC2) == SET)
{
Tx_Flag_Clear(3);
TargetDMA_Channel[2]->CCR &= (uint16_t)(~DMA_CCR1_EN);
DMA_ClearITPendingBit(DMA1_IT_TC2);
}
}