STM32串口协议

目前我总结了两种串口通信时用到的串口协议程序。均学习的原子哥的。

一、定义某个字符为一次接收数据完成,如/n/r。

二、定义两个字符接收时间间隔,如10ms。超过即为第二次接收。

一、程序示意:


二、程序示意、


#include \"delay.h\"
#include \"usart2.h\"
#include \"stdarg.h\"        
#include \"stdio.h\"         
#include \"string.h\"      
//   
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//串口2驱动代码      
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2013/2/22
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved                                     
//     
 
//串口发送缓存区   
__align(8) u8 USART2_TX_BUF[USART2_MAX_SEND_LEN];   //发送缓冲,最大USART2_MAX_SEND_LEN字节
#ifdef USART2_RX_EN                                 //如果使能了接收         
//串口接收缓存区   
u8 USART2_RX_BUF[USART2_MAX_RECV_LEN];              //接收缓冲,最大USART2_MAX_RECV_LEN个字节.
 
 
//通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
//如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
u16 USART2_RX_STA=0;     
void USART2_IRQHandler(void)
{
    u8 res;     
    if(USART2->SR&(1<<5))//接收到数据
    {    
        res=USART2->DR;           
        if(USART2_RX_STA<USART2_MAX_RECV_LEN)        //还可以接收数据
        {
            TIM4->CNT=0;                             //计数器清空
            if(USART2_RX_STA==0)TIM4_Set(1);        //使能定时器4的中断 
            USART2_RX_BUF[USART2_RX_STA++]=res;     //记录接收到的值    
        }else
        {
            USART2_RX_STA|=1<<15;                 //强制标记接收完成
        } 
    }                                            
}   
//初始化IO 串口2
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率   
void USART2_Init(u32 pclk1,u32 bound)
{            
    RCC->APB2ENR|=1<<8;    //使能PORTG口时钟  
    GPIOG->CRH&=0XFFFFFF0F;  //IO状态设置
    GPIOG->CRH|=0X00000030;  //IO状态设置
    RCC->APB2ENR|=1<<2;    //使能PORTA口时钟  
    GPIOA->CRL&=0XFFFF00FF;  //IO状态设置
    GPIOA->CRL|=0X00008B00;  //IO状态设置     
    RCC->APB1ENR|=1<<17;   //使能串口时钟     
    RCC->APB1RSTR|=1<<17;   //复位串口2
    RCC->APB1RSTR&=~(1<<17);//停止复位        
    //波特率设置
    USART2->BRR=(pclk1*1000000)/(bound);// 波特率设置  
    USART2->CR1|=0X200C;     //1位停止,无校验位.
    USART2->CR3=1<<7;      //使能串口2的DMA发送
    UART_DMA_Config(DMA1_Channel7,(u32)&USART2->DR,(u32)USART2_TX_BUF);//DMA1通道7,外设为串口2,存储器为USART2_TX_BUF 
#ifdef USART2_RX_EN         //如果使能了接收
    //使能接收中断
    USART2->CR1|=1<<8;     //PE中断使能
    USART2->CR1|=1<<5;     //接收缓冲区非空中断使能           
    MY_NVIC_Init(2,3,USART2_IRQn,2);//组2,最低优先级 
    TIM4_Init(99,7199);     //10ms中断
    USART2_RX_STA=0;        //清零
    TIM4_Set(0);            //关闭定时器4
#endif                                          
}
//串口2,printf 函数
//确保一次发送数据不超过USART2_MAX_SEND_LEN字节
void u2_printf(char* fmt,...)  
{  
    va_list ap;
    va_start(ap,fmt);
    vsprintf((char*)USART2_TX_BUF,fmt,ap);
    va_end(ap);
    while(DMA1_Channel7->CNDTR!=0);  //等待通道7传输完成   
    UART_DMA_Enable(DMA1_Channel7,strlen((const char*)USART2_TX_BUF));  //通过dma发送出去
}
//定时器4中断服务程序            
void TIM4_IRQHandler(void)
{   
    if(TIM4->SR&0X01)//是更新中断
    {                  
        USART2_RX_STA|=1<<15; //标记接收完成
        TIM4->SR&=~(1<<0);     //清除中断标志位          
        TIM4_Set(0);            //关闭TIM4  
    }       
}
//设置TIM4的开关
//sta:0,关闭;1,开启;
void TIM4_Set(u8 sta)
{
    if(sta)
    {
        TIM4->CNT=0;         //计数器清空
        TIM4->CR1|=1<<0;     //使能定时器4
    }else TIM4->CR1&=~(1<<0);//关闭定时器4     
}
//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数         
void TIM4_Init(u16 arr,u16 psc)
{
    RCC->APB1ENR|=1<<2;    //TIM4时钟使能    
    TIM4->ARR=arr;   //设定计数器自动重装值   
    TIM4->PSC=psc;   //预分频器
    TIM4->DIER|=1<<0;   //允许更新中断               
    TIM4->CR1|=0x01;     //使能定时器4           
    MY_NVIC_Init(1,3,TIM4_IRQn,2);//抢占2,子优先级3,组2    在2中优先级最低                                 
}
#endif       
///USART2 DMA发送配置部分//               
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址    
void UART_DMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar)
{
    RCC->AHBENR|=1<<0;         //开启DMA1时钟
    delay_us(5);
    DMA_CHx->CPAR=cpar;      //DMA1 外设地址 
    DMA_CHx->CMAR=cmar;      //DMA1,存储器地址     
    DMA_CHx->CCR=0X00000000; //复位
    DMA_CHx->CCR|=1<<4;        //从存储器读
    DMA_CHx->CCR|=0<<5;        //普通模式
    DMA_CHx->CCR|=0<<6;        //外设地址非增量模式
    DMA_CHx->CCR|=1<<7;        //存储器增量模式
    DMA_CHx->CCR|=0<<8;        //外设数据宽度为8位
    DMA_CHx->CCR|=0<<10;       //存储器数据宽度8位
    DMA_CHx->CCR|=1<<12;       //中等优先级
    DMA_CHx->CCR|=0<<14;       //非存储器到存储器模式            
} 
//开启一次DMA传输
void UART_DMA_Enable(DMA_Channel_TypeDef*DMA_CHx,u8 len)
{
    DMA_CHx->CCR&=~(1<<0);       //关闭DMA传输 
    DMA_CHx->CNDTR=len;          //DMA1,传输数据量 
    DMA_CHx->CCR|=1<<0;          //开启DMA传输
}      
/                                    

                             
                     

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值