串口中断输出
串口中断分别输出单个字符和字符串
①串口引脚
选择PA9和PA10充当串口的发送引脚和接收引脚。
②中断控制器NVIC配置
void Usart1_NVICInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
③串口的初始化配置
初始化GPIO和USART,引脚复用并且接收中断和串口使能。
void Usart1_Init(uint32_t BaudRate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
USART_InitStructure.USART_BaudRate = BaudRate;
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;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_Init(USART1,&USART_InitStructure);
Usart1_NVICInit();
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1,ENABLE);
}
注意事项
需要注意的是,不可写成
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9 | GPIO_PinSource10,GPIO_AF_USART1);
因为在 STM32 的 GPIO 初始化中,类似
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;是可以的,因为GPIO_Init()内部会遍历所有位,逐一配置。但GPIO_PinAFConfig()是专门为配置复用功能(Alternate Function)设计的,它直接操作 AFR(Alternate Function Register) 寄存器。AFR 寄存器将每个引脚的 4 位复用配置独立存放,不支持批量写入不同引脚的复用值(因为每个引脚可能配置成不同的 AF 编号)。如果强行用|传入多个引脚,函数无法知道你想给每个引脚分别配什么 AF 值。
④发送单个字节和字符串的函数
查看手册可知TXE(发送标志位)和RXNE(接收标志位)是硬件自动清零,但是TC(发送完成标志位)是需要软件清零的。

发送单个字节函数
单个字符发送完之后,串口输出
void Usart_SendByte(USART_TypeDef *Usart_Tx,uint8_t ch)
{
USART_SendData(Usart_Tx,ch);
while(USART_GetFlagStatus(Usart_Tx,USART_FLAG_TXE) == RESET);
}
发送字符串函数
注意不要写成u8或者其它
unsigned int 与一般的 uint8_t 是有区别的
uint8_t unsigned int 大小固定 固定为1字节 大小可变(通常≥2字节) 范围 0~255 0~4294967295 应用场景 需要精确控制内存布局、网络协议、硬件寄存器时 需要通用整数运算且不关心大小时
do...while:先执行后判断
指针索引,如果没有遇到字符串结束符,就一直发送单个字节。
用TC标志位来判断是因为TC 是在整个字节(包括停止位)完全发出后才置位。
记得最后清除TC标志位
void Usart_String(USART_TypeDef *Usart_Tx,char *str)
{
unsigned int i = 0;
do
{
Usart_SendByte(Usart_Tx, *(str + i));
i++;
}while(*(str + i) != '\0');
while(USART_GetFlagStatus(Usart_Tx,USART_FLAG_TC) == RESET);
USART_ClearFlag(Usart_Tx, USART_FLAG_TC);
}
⑤串口中断函数
单片机每接收到一个完整的字节,就会进入一次串口中断函数。
如果发现接收标志位置1了,就发送接收到的字节
void USART1_IRQHandler(void)
{
uint8_t temp;
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
{
temp = USART_ReceiveData(USART1);
USART_SendData(USART1,temp);
}
}
⑥主函数
int main()
{
u8 i=0;
SysTick_Init(168);
Usart1_Init(9600);
LED_Init();
Usart_SendByte(USART1,'A');
Usart_String(USART1,"CHINA");
while(1)
{
i++;
if(i%20==0)
{
LED1=!LED1;
}
delay_ms(10);
}
}
⑦结果
串口输出

更多推荐



所有评论(0)