STM32 串口3使用代码

来源:互联网 发布:日历软件下载 编辑:程序博客网 时间:2024/05/16 18:44

文章转载http://bbs.21ic.com/icview-850883-1-1.html

有用过STM32F103C8T6  USART3的兄弟吗?? 今天我测试这个模块,发现PB11作为rx可以收到数据,并中断,但PB10却发不出数据,奇怪 


void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)         
        { 
               //检查参数合法性
             assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
             assert_param(IS_NVIC_OFFSET(Offset));           
             SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//设置NVIC的向量表偏移寄存器
             //用于标识向量表是在CODE区还是在RAM区
        }
   //设置NVIC分组
   //NVIC_Group:NVIC分组 0~4 总共5组 
        
   void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)         
        { 
             u32 temp,temp1;          
             temp1=(~NVIC_Group)&0x07;//取后三位
             temp1<<=8;
             temp=SCB->AIRCR;  //读取先前的设置
             temp&=0X0000F8FF; //清空先前分组
             temp|=0X05FA0000; //写入钥匙
             temp|=temp1;           
             SCB->AIRCR=temp;  //设置分组                                                         
        }
    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<<NVIC_Channel;//使能中断位(要清除的话,相反操作就OK)
             else NVIC->ISER[1]|=1<<(NVIC_Channel-32);   

             //NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;//设置响应优先级和抢断优先级 
                 NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;                                                            
         }
                 

     //不能在这里执行所有外设复位!否则至少引起串口不工作.                    
     //把所有时钟寄存器复位

    void MYRCC_DeInit(void)
         {                                                                                                                             
             RCC->APB1RSTR = 0x00000000;//复位结束                         
             RCC->APB2RSTR = 0x00000000; 
          
               RCC->AHBENR = 0x00000014;  //flash时钟,闪存时钟使能.DMA时钟关闭          
               RCC->APB2ENR = 0x00000000; //外设时钟关闭.                           
               RCC->APB1ENR = 0x00000000;   
             RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                                                                                                                                  
             RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]                                         
             RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
             RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP                     
             RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE 
             RCC->CIR = 0x00000000;     //关闭所有中断
             //配置向量表                                  

             MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

         }

    void Stm32_Clock_Init(unsigned char PLL)
         {
              unsigned char temp=0;   

              MYRCC_DeInit();                  //复位并配置向量表
              RCC->CR|=0x00010000;  //外部高速时钟使能HSEON
              while(!(RCC->CR>>17));//等待外部时钟就绪
              RCC->CFGR=0X00000000; //APB1/2=DIV2;AHB=DIV1;
              PLL-=2;//抵消2个单位
              RCC->CFGR|=PLL<<18;   //设置PLL值 2~16
              RCC->CFGR|=1<<16;          //PLLSRC ON 
              FLASH->ACR|=0x32;          //FLASH 2个延时周期

              RCC->CR|=0x01000000;  //PLLON
              while(!(RCC->CR>>25));//等待PLL锁定
              RCC->CFGR|=0x00000002;//PLL作为系统时钟         
              while(temp!=0x02)     //等待PLL作为系统时钟设置成功
                   {   
                       temp=RCC->CFGR>>2;
                       temp&=0x03;
                   }    
         }
void Stm32_Gpio_Init(void)
{
  RCC->APB2ENR|=0XFFFF;   //GPIO CLOCK EN;
   RCC->APB1ENR|=0Xffffffff;   //GPIO CLOCK EN;
//4 INPUT;3 OUT PUT
GPIOA->CRL=0x33334b00;
GPIOA->CRH=0x000348b0;
GPIOB->CRL=0x40000000;
//GPIOB->CRH=0x00004b44;
   GPIOB->CRH=0x00008f44;
//  AFIO->MAPR=0X00;                 
}
      void uart3_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->APB1ENR|=1<<18;  //使能串口时钟
             RCC->APB1RSTR|=1<<18;   //复位串口1
              RCC->APB1RSTR&=~(1<<18);//停止复位                      
              //波特率设置
               USART3->BRR=mantissa; // 波特率设置         
                  USART3->CR1|=0X200C;  //1位停止,无校验位
             USART3->CR1|=1<<8;    //PE中断使能
              USART3->CR1|=1<<5;    //接收缓冲区非空中断使能                    
              MY_NVIC_Init(7,0,USART3_IRQChannel,4);//组2,最低优先级 
         }
  void usart3_send8bit(unsigned char indata )
   {
              while (!(USART3->SR & USART_FLAG_TXE));
              USART3->DR = (indata& 0x1FF);
               while (!(USART3->SR & USART_FLAG_TC));
   }

main ()
{
unsigned int test_data=0;
                Stm32_Clock_Init(9);
              Stm32_Gpio_Init();
              uart3_init(72,9600);         
led2=1;
led3=1;        
while(1)         
{                          
                          led1++;
                          delay1ms(10); 
                          usart3_send8bit(0);
                           delay1ms(10);
                          //usart1_send8bit(0);

}
}


我把USART2的TX连到PB11上,USART3可以进入中断,而且收到的数据正确,就是PB10发不出数,

usart3的代码是在STM32f103vet6上用过的, 问题出在哪里呢



这个程序时钟有问题,修改   RCC->APB2ENR=0X481D;   //GPIO CLOCK EN;
                                           RCC->APB1ENR=0X12060801;   //GPIO CLOCK EN;
就行了


ScreenClip.png


我的程序是定时发送数据,程序是这样的:
u16 temp;
u8 TX_temp[3];
u8 t;
void TIM3_IRQHandler(void)
{          
    if(TIM3->SR&0X0001)
    {
        temp=DS18B20_Get_Temp();
        TX_temp[0]=(u8)temp;
        temp=temp>>8;
        TX_temp[1]=(u8)temp;
        for(t=0;t<2;t++)
        {
            USART1->DR=TX_temp[t];
            while((USART1->SR&0X40)==0);
        } 
    }   
    TIM3->SR&=~(1<<0);
}
我查看变量temp和TX_temp的值都是对的,但是USART1->DR寄存器的值却一直都是0?
我也不知道为啥,求指点


乱码一般是波特率的原因. 
串口3的时钟是串口1的一半.


 在<<不完全手册>>2.7.3节,有这么一段话:

void USART1_IRQHandler(void)函数是一个串口1中断响应函数,当串口1发生了相应的中断后,就会跳到该函数执行。这里我们设计了一个小小的接收协议:通过这个函数,配合一个数组USART_RX_BUF[64],一个接收状态寄存器USART_RX_STA实现对串口数据的接收管理。USART_RX_BUF的最大值为64,也就是一次接收的数据最大不能超过64个字节。USART_RX_STA是一个接收状态寄存器其各的定义如下表:

USART_RX_STA

bit7

bit6

bit5

bit4

bit3

bit2

bit1

bit0

接收完成标志

接收 到0X0D标志

接收到的有效数据个数

                              2.7.2.2 接收状态寄存器位定义表

设计思路如下:

当接收到从电脑发过来的数据,把接收到的数据保存在USART_RX_BUF中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(0X0D0X0A)的第一个字节0X0D时,计数器将不再增加,等待0X0A的到来,而如果0X0A没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到0X0A,则标记USART_RX_STA的第七位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过64个了,则会丢弃前面的数据,重新接收。


0 0