STM32串口接收中断与空闲中断
根据控制寄存器1(USART1_CR1)的RXNEIE(接收中断)和IDLEIE(空闲中断)
USART1->CR1 |=(1<<5);//打开接收中断
USART1->CR1 |=(1<<4);//打开空闲中断
//也可以写为标准库函数
//每来一个字节 ,就触发一次中断去中断服务函数当中及时接收
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//空闲中断 打开IDLE 表示数据接收完成 可以进行处理了
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//这两个中断源触发同一个 中断通道
串口1中断服务函数:
u8 rev_buff[1000];
u8 usart1_flag=0;
void USART1_IRQHandler(void)//中断服务函数
{
static u8 i=0;
if(USART1->SR &(1<<5))//判断是否读取,读取内容
//if(USART_GetITStatus(USART1,USART_IT_RXNE)==1)
{
rev_buff=USART1->DR;
i++;
}
if(USART1->SR &(1<<4))//判断是否空闲,停止读取
//if(USART_GetITStatus(USART1,USART_IT_IDLE)==1)
{
USART1->SR;//读入USART_SR寄存器,清零
USART1->DR;//读入USART_DR寄存器,清零
rev_buff='\0';
i=0;
usart1_flag=1;//传输完成标志位
printf("rev_buff=%s\r\n",rev_buff);
}
}
串口1配置函数:
/*
Function name:Usart1_Config
Description:串口1初始化
param:brr-->波特率
retval:None
Remarks:
PA9:复用推挽输出
PA10:复用
*/
void Usart1_Config(u32 brr)
{
RCC->AHB2ENR|=(1<<0);//PA时钟
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC->APB2ENR|=(1<<4);//USART1时钟
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//IO PA9
GPIOA->MODER &=~(3<<18);//清零
GPIOA->MODER |=(2<<18);//复用
GPIOA->OTYPER&=~(1<<9);//推挽
GPIOA->AFR[1]|=(7<<4);//选择USART1复用功能
//PA10
GPIOA->MODER &=~(3<<20);//清零
GPIOA->MODER|=(2<<20);//复用
GPIOA->AFR[1]|=(7<<8);//选择USART1复用功能
//PA9-复用推挽
//PA10 -浮空输入
//GPIO_InitTypeDef GPIO_InitStruct={0};
//GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//串口1 发送引脚用 复用推挽
//GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;//选中引脚
//GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//io口速率,一般最大就行
//GPIO_Init(GPIOA,&GPIO_InitStruct);
//GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//串口1 发送引脚用 复用推挽
//GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;//选中引脚
//GPIO_Init(GPIOA,&GPIO_InitStruct);
//USART1 USARTDIV是一个无符号定点数(div),
float div;
u32 div_f,div_m;//div_f是USARTDIV的小数部分,div_m是USARTDIV的整数部分
div=84000000.0/16/brr;
div_m=(u32)div;
div_f=(div-div_m)*16+0.5;
USART1->BRR=div_m<<4|div_f;
USART1->CR1 |=(3<<2);//发送器/接收器 使能
USART1->CR1 &=~(1<<10);//禁止奇偶校验
USART1->CR1 &=~(1<<12);//字长 8位数据位
USART1->CR1 &=~(1<<15);//16倍过采样
USART1->CR2 &=~(3<<12);//1位停止位
Usart1_Nvic();//中断使能
USART1->CR1 |=(1<<13);//使能USART1
//USART_InitTypeDef USART1_InitStruct={0};
//USART1_InitStruct.USART_BaudRate=115200;//波特率
//USART1_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制,NONE就是不用硬件流
//USART1_InitStruct.USART_Mode=USART_Mode_Rx |USART_Mode_Tx;//接收跟发送都打开,规定用 或
//USART1_InitStruct.USART_Parity=USART_Parity_No;//奇偶校验,不要
//USART1_InitStruct.USART_StopBits=USART_StopBits_1;//1个停止位
//USART1_InitStruct.USART_WordLength=USART_WordLength_8b;//8个数据位
//USART_Init(USART1,&USART1_InitStruct);//按照结构体,初始化串口1
//启动
//USART_Cmd(USART1,ENABLE);
}
/*
Function name:Usart1_Nvic
Description:串口接收与空闲中断完成任意字符串的接收
param:None
retval:
Remarks:
*/
void Usart1_Nvic(void)
{
USART1->CR1 |=(1<<5);//打开接收中断
USART1->CR1 |=(1<<4);//打开空闲中断
//配置优先级
NVIC_SetPriority(USART1_IRQn,5);//优先级 占先=1 次级=1
NVIC_EnableIRQ(USART1_IRQn);//使能
//配置 串口RXNE 接收寄存器非空 表示来了一个字节数据
//NVIC_InitTypeDef NVIC_InitStruct={0};
//NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;//串口1的中断通道,串口1的所有中断源 都共用这一个通道
//NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
//NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
//NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
//NVIC_Init(&NVIC_InitStruct);
}
u8 rev_buff[1000];
u8 usart1_flag=0;
void USART1_IRQHandler(void)//中断服务函数
{
static u8 i=0;
if(USART1->SR &(1<<5))//判断是否读取,读取内容
//if(USART_GetITStatus(USART1,USART_IT_RXNE)==1)
{
rev_buff=USART1->DR;
i++;
}
if(USART1->SR &(1<<4))//判断是否空闲,停止读取
//if(USART_GetITStatus(USART1,USART_IT_IDLE)==1)
{
USART1->SR;//读入USART_SR寄存器,清零
USART1->DR;//读入USART_DR寄存器,清零
rev_buff='\0';
i=0;
usart1_flag=1;//传输完成标志位
printf("rev_buff=%s\r\n",rev_buff);
}
}
//重定向,即fputc重新定义,然后在keil的魔法棒->Target->勾选Use Micro LIB
//通过此操作可以通过串口1使用printf
int fputc(int c,FILE * stream)
{
while(!(USART1->SR & (1<<7)));
//如果TC标志位不成立,就卡死等待 成立
//while(USART_GetFlagStatus(USART1,USART_FLAG_TC) !=1)
USART1->DR=c;
return c;
}
Usart1_Nvic();需要的中断时就删除屏蔽,不需要时就打开屏蔽
重定向是在Keil软件中使用printf函数
主函数:
while(1)
{
if(usart1_flag==1)
{
if(strcmp((const char *)rev_buff,(const char *)"LED1ON")==0)
{
LED1_ON;
}
if(strcmp((const char *)rev_buff,(const char *)"LED1OFF")==0)
{
LED1_OFF;
}
usart1_flag=0;
}
}
注意:
strcmp((const char *)rev_buff,(const char *)"LED1ON")
//strcmp((const )a,(const )b);固定格式
//表示将该指针指向的数据视为常量字符,不允许对其内容进行修改。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_50866235/article/details/143462598
|