1,初始化IO 串口1,pclk2:PCLK2时钟频率(Mhz),波特率9600, 中断向量一般配置用中断方式接收数据
I/O口配置:TXD配置为复用推挽输出(GPIO_Mode_AF_PP),RXD配置为浮空输入(GPIO_Mode_IN_FLOATING);
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
RCC->APB2ENR|=1<<14; //使能串口时钟
GPIOA->CRH&=0XFFFFF00F;
GPIOA->CRH|=0X000008B0;//IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
#ifdef EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=1<<8; //PE中断使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
#endif
}
首先通过时钟频率和波特率计算出“mantisa”这个参数是一会儿赋值给USARTx->BRR 寄存器的,来设置串口的波特率
使能IO口时钟和所用串口的时钟
设置IO口(TX、RX),设置为复用功能,复用为USART
设置波特率,是否过采样(16倍过采样来保证较好的容错性),数据长度和有无校验位
使能发送和接收
使能中断,并且设置中断的优先级以及优先级分组
使能串口
NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
u8 IPRADDR=NVIC_Channel/4; //每组只能存4个,得到组地址
u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
IPROFFSET=IPROFFSET*8+4; //得到偏移的确切位置
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<
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IPR[IPRADDR]|=temp<
}
2,STM32串口接收数据
#ifdef EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[64]; //接收缓冲,最大64个字节.
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
u8 USART_RX_STA=0; //接收状态标记
void USART1_IRQHandler(void)
{
u8 res;
if(USART1->SR&(1<<5))//接收到数据
{
res=USART1->DR;
if((USART_RX_STA&0x80)==0)//接收未完成
{
if(USART_RX_STA&0x40)//接收到了0x0d
{
if(res!=0x0a)
USART_RX_STA=0;//接收错误,重新开始
else
USART_RX_STA|=0x80; //接收完成了
}
else //还没收到0X0D
{
if(res==0x0d)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)
USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif
是定义了一个接收缓冲数组,来存放接收到的数据,每个元素可以存放一个字节的数据,数组的长度为USART_REC_LEN。操作系统的部分暂时忽略,接下来定义了一个16位的接收状态标记USART_RX_STA
它的第15位是接收完成标志,第14位是接收到0x0d的标志,而0-13位表示接收到的有效字节的数目。当接收到一个数据后,把接收到的数据(DR寄存器中的值)暂存在中间变量中,先检验接收是否完成,若未完成,检验是否接收到0x0d,如果接收到,修改状态标记,然后把中间变量的值赋给缓冲数组,将状态标记的值自增,完成对一个字节的接收。
3,STM32串口发送数据:将要发送的数据(8位)赋给数据寄存器(DR)然后等待发送完成。
len=USART_RX_STA&0x3f;//得到此次接收到的数据长度
for(t=0;t
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//等待发送结束
}
printf("nn");//插入换行
USART_RX_STA=0;
1,初始化IO 串口1,pclk2:PCLK2时钟频率(Mhz),波特率9600, 中断向量一般配置用中断方式接收数据
I/O口配置:TXD配置为复用推挽输出(GPIO_Mode_AF_PP),RXD配置为浮空输入(GPIO_Mode_IN_FLOATING);
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
RCC->APB2ENR|=1<<14; //使能串口时钟
GPIOA->CRH&=0XFFFFF00F;
GPIOA->CRH|=0X000008B0;//IO状态设置
RCC->APB2RSTR|=1<<14; //复位串口1
RCC->APB2RSTR&=~(1<<14);//停止复位
//波特率设置
USART1->BRR=mantissa; // 波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位.
#ifdef EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=1<<8; //PE中断使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
#endif
}
首先通过时钟频率和波特率计算出“mantisa”这个参数是一会儿赋值给USARTx->BRR 寄存器的,来设置串口的波特率
使能IO口时钟和所用串口的时钟
设置IO口(TX、RX),设置为复用功能,复用为USART
设置波特率,是否过采样(16倍过采样来保证较好的容错性),数据长度和有无校验位
使能发送和接收
使能中断,并且设置中断的优先级以及优先级分组
使能串口
NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
u8 IPRADDR=NVIC_Channel/4; //每组只能存4个,得到组地址
u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
IPROFFSET=IPROFFSET*8+4; //得到偏移的确切位置
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<
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IPR[IPRADDR]|=temp<
}
2,STM32串口接收数据
#ifdef EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[64]; //接收缓冲,最大64个字节.
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
u8 USART_RX_STA=0; //接收状态标记
void USART1_IRQHandler(void)
{
u8 res;
if(USART1->SR&(1<<5))//接收到数据
{
res=USART1->DR;
if((USART_RX_STA&0x80)==0)//接收未完成
{
if(USART_RX_STA&0x40)//接收到了0x0d
{
if(res!=0x0a)
USART_RX_STA=0;//接收错误,重新开始
else
USART_RX_STA|=0x80; //接收完成了
}
else //还没收到0X0D
{
if(res==0x0d)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)
USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif
是定义了一个接收缓冲数组,来存放接收到的数据,每个元素可以存放一个字节的数据,数组的长度为USART_REC_LEN。操作系统的部分暂时忽略,接下来定义了一个16位的接收状态标记USART_RX_STA
它的第15位是接收完成标志,第14位是接收到0x0d的标志,而0-13位表示接收到的有效字节的数目。当接收到一个数据后,把接收到的数据(DR寄存器中的值)暂存在中间变量中,先检验接收是否完成,若未完成,检验是否接收到0x0d,如果接收到,修改状态标记,然后把中间变量的值赋给缓冲数组,将状态标记的值自增,完成对一个字节的接收。
3,STM32串口发送数据:将要发送的数据(8位)赋给数据寄存器(DR)然后等待发送完成。
len=USART_RX_STA&0x3f;//得到此次接收到的数据长度
for(t=0;t
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//等待发送结束
}
printf("nn");//插入换行
USART_RX_STA=0;
举报