串口作为 MCU 的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的 MCU 都会带有串口,这块MM32F031提供了两路串口,分别为引脚12,13 和30,31两组。
支持异步方式下 RS-232S 协议,符合工业标准 16550。
支持 DMA 请求
全双工异步操作
内置 16 位的可编程波特率发生器。
单独分开的发送和接收缓冲寄存器
内置一个字节发送和接收缓冲
发送和接收数据低位在前
一个起始位开始,后面接数据位,输出的数据长度可为 5 位、6 位、7 位、8 位,最后为停止位。
另外可选择是否有加奇偶校验位,奇偶校验位在数据位之后停止位之前。
支持硬件奇数或者偶数校验产生和侦测
线断开产生和侦测
支持硬件自动流控制
支持下面中断源:
- 发送端 BUFFER 空
- 接收端数据有效
- 接收缓冲缓存溢出
- 帧错误
- 奇偶校验错误
- 断开错误
资源丰富,功能强劲。对于我个人而言,一般用串口就是调试程序,和数据
通信这两个功能。MM32
MiniBoard上板载了两个RS232串口,其中一个连接的9针串口,一个用的插针,另外,还附带有一条双母头的串口线。这次就用这个9针串口与电脑进行通信。
串口设置的一般步骤可以总结为如下几个步骤:
1) 串口时钟使能,GPIO 时钟使能
2) 串口复位
3) GPIO 端口模式设置
4) 串口参数初始化
5) 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
6) 使能串口
7) 编写中断处理函数
以下就是程序代码:
void uart_nvic_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
UART_InitTypeDef UART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1|RCC_APB2Periph_GPIOA, ENABLE); //使能UART1,GPIOA时钟
//UART1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//UART 初始化设置
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
UART_InitStructure.UART_BaudRate = bound;//串口波特率
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//字长为8位数据格式
UART_InitStructure.UART_StopBits = UART_StopBits_1;//一个停止位
UART_InitStructure.UART_Parity = UART_Parity_No;//无奇偶校验位
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;//无硬件数据流控制
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; //收发模式
UART_Init(UART1, &UART_InitStructure); //初始化串口1
UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);//开启串口接受中断
UART_Cmd(UART1, ENABLE); //使能串口1
//UART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//UART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
}
void UART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(UART_GetITStatus(UART1, UART_IT_RXIEN) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
UART_ClearITPendingBit(UART1,UART_IT_RXIEN);
Res =UART_ReceiveData(UART1); //读取接收到的数据
if((Res==0x0d)&&((UART_RX_STA&0X3FFF)>0))
{
UART_RX_STA|=0x4000;
UART_RX_BUF[UART_RX_STA&0X3FFF]=Res ;
UART_RX_STA++;
}
else if((UART_RX_STA&0x4000)&&((UART_RX_STA&0X3FFF)>0))//接收到了0x0d
{
if(Res==0x0a)
{
UART_RX_STA|=0x8000;
}
UART_RX_BUF[UART_RX_STA&0X3FFF]=Res ;
UART_RX_STA++;
}
else{
UART_RX_BUF[UART_RX_STA&0X3FFF]=Res ;
UART_RX_STA++;
UART_RX_STA=UART_RX_STA&0X3FFF;
if((UART_RX_STA)>(UART_REC_LEN-1))
UART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}