STM32使用串口中断发送和接受数据
2014-12-24 15:07
1046 查看
这里用到的芯片为STM32F103,使用中断进行串口的接受和发送数据。
这里使用直接操作寄存器的方式,使用库函数和这个类似,只是改为调用响应的库函数即可。
配置串口和复用的IO口
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//分频
mantissa=temp; //分频得到的整数部分
fraction=(temp-mantissa)*16; //小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能GPIOA时钟
RCC->APB2ENR|=1<<14; //使能串口1的时钟
RCC->APB2ENR|=1<<0; //(+)Alternate function I/O clock enable 好像不要也行,是不是默认是使能的?
GPIOA->CRH&=0XFFFFF00F;//IO对应位清零
GPIOA->CRH|=0X000008B0;//IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
USART1->BRR=mantissa;//设置波特率
USART1->CR1|=0X200C; //1位停止位,无校验位
//使能发送中断
USART1->CR1|=1<<6;
USART1->SR&=(~(1<<6));//清除中断标志位
//使能接收终端
USART1->CR1|=1<<8; //PE中断使能?
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQn,2);//第二组中断,最低优先级
}
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位
if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中断位
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IP[NVIC_Channel]|=temp<<4;//设置响应优先级和抢断优先级
}
//发送中断设置
void USART_SendXByte(USART_TypeDef* USARTx, u16 SendByteNum)
{
HAVE_SEND_LEN=0;//清零已发数据长度标记(全局变量)
ALL_SEND_LEN=SendByteNum;//ALL_SEND_LEN为这一次需要发送的数据长度
IsSending=1;
USART1->DR=SEND_BUF[HAVE_SEND_LEN];
HAVE_SEND_LEN++;
}
中断处理函数
u16 USART_RX_STA=0; //用于标记接收到了一位数据
//u16 USART_SEND_COMPLETE=1; //发送完成标记
u8 REC;//用于接收串口收到的一个字节的数据,全局变量,在其他程序中读这个变量即可取出串口所接收的数据
u16 HAVE_SEND_LEN=0;
u16 ALL_SEND_LEN=0;
char SEND_BUF[USART_SEND_LEN];//未用
char REC_BUF[USART_REC_LEN];//未用
void USART1_IRQHandler(void)
{
if(USART1->SR&(1<<5))//接收到数据
{
USART_RX_STA=1;//置标记位,读取此标记位为真,则读取REC即可取出接收的数据
CountReciByte++;
REC=USART1->DR;
}
if(USART1->SR&(1<<6))//(+)·发送一个字节完成中断
{
if(HAVE_SEND_LEN<ALL_SEND_LEN)
{
USART1->DR=SEND_BUF[HAVE_SEND_LEN];//SEND_BUF[]为全局变量,存放要发送的数据
HAVE_SEND_LEN++;
}
if(HAVE_SEND_LEN==ALL_SEND_LEN)
{
USART_SEND_COMPLETE=1;
while(!(USART1->SR&(1<<6)))
{
//等待最后一个字节发送完成
}
USART1->SR&=(~(1<<6)); //清除发送中断标记
IsSending=0;
}
}
}
main函数
int main(void)
{
Stm32_Clock_Init(9);
uart_init(72,115200);
delay_init(72);
while(1)//回显"每次"接收到的前10个字节
{
if((1==USART_RX_STA)&&(CountReciByte<=10))
{
SEND_BUF[SerialBufOffset] = REC;
USART_RX_STA=0;
SerialBufOffset++;
if(10==SerialBufOffset)
{
ReadZiku(100,100,SEND_BUF,Black, White);
//strcpy(SEND_BUF, "ABCDEFGHIJKLDR");
USART_SendXByte(USART1, SEND_BUF, 10);
//memset(SEND_BUF,0,sizeof(SEND_BUF));
SerialBufOffset=0;
CountReciByte=0;
//delay_ms(1000);
}
USART_RX_STA=0;//为了不让下一次接受上一次未取出的那个字节
}
}
这里使用直接操作寄存器的方式,使用库函数和这个类似,只是改为调用响应的库函数即可。
配置串口和复用的IO口
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//分频
mantissa=temp; //分频得到的整数部分
fraction=(temp-mantissa)*16; //小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能GPIOA时钟
RCC->APB2ENR|=1<<14; //使能串口1的时钟
RCC->APB2ENR|=1<<0; //(+)Alternate function I/O clock enable 好像不要也行,是不是默认是使能的?
GPIOA->CRH&=0XFFFFF00F;//IO对应位清零
GPIOA->CRH|=0X000008B0;//IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
USART1->BRR=mantissa;//设置波特率
USART1->CR1|=0X200C; //1位停止位,无校验位
//使能发送中断
USART1->CR1|=1<<6;
USART1->SR&=(~(1<<6));//清除中断标志位
//使能接收终端
USART1->CR1|=1<<8; //PE中断使能?
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQn,2);//第二组中断,最低优先级
}
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位
if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中断位
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IP[NVIC_Channel]|=temp<<4;//设置响应优先级和抢断优先级
}
//发送中断设置
void USART_SendXByte(USART_TypeDef* USARTx, u16 SendByteNum)
{
HAVE_SEND_LEN=0;//清零已发数据长度标记(全局变量)
ALL_SEND_LEN=SendByteNum;//ALL_SEND_LEN为这一次需要发送的数据长度
IsSending=1;
USART1->DR=SEND_BUF[HAVE_SEND_LEN];
HAVE_SEND_LEN++;
}
中断处理函数
u16 USART_RX_STA=0; //用于标记接收到了一位数据
//u16 USART_SEND_COMPLETE=1; //发送完成标记
u8 REC;//用于接收串口收到的一个字节的数据,全局变量,在其他程序中读这个变量即可取出串口所接收的数据
u16 HAVE_SEND_LEN=0;
u16 ALL_SEND_LEN=0;
char SEND_BUF[USART_SEND_LEN];//未用
char REC_BUF[USART_REC_LEN];//未用
void USART1_IRQHandler(void)
{
if(USART1->SR&(1<<5))//接收到数据
{
USART_RX_STA=1;//置标记位,读取此标记位为真,则读取REC即可取出接收的数据
CountReciByte++;
REC=USART1->DR;
}
if(USART1->SR&(1<<6))//(+)·发送一个字节完成中断
{
if(HAVE_SEND_LEN<ALL_SEND_LEN)
{
USART1->DR=SEND_BUF[HAVE_SEND_LEN];//SEND_BUF[]为全局变量,存放要发送的数据
HAVE_SEND_LEN++;
}
if(HAVE_SEND_LEN==ALL_SEND_LEN)
{
USART_SEND_COMPLETE=1;
while(!(USART1->SR&(1<<6)))
{
//等待最后一个字节发送完成
}
USART1->SR&=(~(1<<6)); //清除发送中断标记
IsSending=0;
}
}
}
main函数
int main(void)
{
Stm32_Clock_Init(9);
uart_init(72,115200);
delay_init(72);
while(1)//回显"每次"接收到的前10个字节
{
if((1==USART_RX_STA)&&(CountReciByte<=10))
{
SEND_BUF[SerialBufOffset] = REC;
USART_RX_STA=0;
SerialBufOffset++;
if(10==SerialBufOffset)
{
ReadZiku(100,100,SEND_BUF,Black, White);
//strcpy(SEND_BUF, "ABCDEFGHIJKLDR");
USART_SendXByte(USART1, SEND_BUF, 10);
//memset(SEND_BUF,0,sizeof(SEND_BUF));
SerialBufOffset=0;
CountReciByte=0;
//delay_ms(1000);
}
USART_RX_STA=0;//为了不让下一次接受上一次未取出的那个字节
}
}
相关文章推荐
- stm32-串口使用IDLE中断接受不定长数据方法
- STM32—无需中断来实现使用DMA接收串口数据(原创)
- STM32L1XX使用HAL_UART_Transmit_DMA发送串口数据
- STM32—无需中断来实现使用DMA接收串口数据(原创)
- 基于STM32CT117E竞赛板(STM32f103RB) 使用USART串口发送数据
- STM8S003F使用IO口模拟串口(三)使用中断方式发送和接收数据
- STM32使用串口IDLE中断的两种接收不定长数据的方式
- 关于RS485通讯中使用STM32串口以DMA方式发送数据丢失字节的问题
- STM32—无需中断来实现使用DMA接收串口数据
- STM32 使用HAL库做串口的DMA发送和中断接收
- STM32串口使用IDLE中断接收不定长数据原理与源程序
- STM32 使用 printf 发送数据配置方法 -- 串口 UART, JTAG SWO, JLINK RTT
- STM32使用DMA加串口空闲中断接收数据
- 【stm32】实现STM32的串口数据发送和printf函数重定向
- STM32的USART发送数据时如何使用TXE和TC标志
- [Socket网络编程]由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
- stm32串口中断收发数据环形缓冲区的设计
- stm32 串口发送数据第一字节丢失
- 【stm32】实现STM32的串口数据发送和printf函数重定向
- STM32串口中断使用