打印
[其他ST产品]

(学习经验)如何从头文件开始设置STM32串口通讯

[复制链接]
71|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
duo点|  楼主 | 2023-12-20 11:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
运用STM32的库函数时,有时候为了看懂一句语句需要翻遍整个头文件,找到头文件中预定义的名字到底代表的是什么意思,具体寄存器设置的数值是多少,相当麻烦。我花了一天的时间才明白串口设置的具体过程,只是库函数想的比较周全。下面是我调试好的串口设置程序,头文件是我自己定义的,舍去了库文件中繁琐的结构体定义……    首先定义头文件:

//*********************控制时钟的一些寄存器*********************

//RCC-Register

//

#define RCC_CR        (*((volatile unsigned long *)0x40021000))

#define RCC_CFGR      (*((volatile unsigned long *)0x40021004))

#define RCC_CIR       (*((volatile unsigned long *)0x40021008))

#define RCC_APB2RSTR  (*((volatile unsigned long *)0x4002100C))

#define RCC_APB1RSTR  (*((volatile unsigned long *)0x40021010))

#define RCC_AHBENR    (*((volatile unsigned long *)0x40021014))

#define RCC_APB2ENR   (*((volatile unsigned long *)0x40021018))

#define RCC_APB1ENR   (*((volatile unsigned long *)0x4002101C))

#define RCC_BDCR      (*((volatile unsigned long *)0x40021020))

#define RCC_CSR       (*((volatile unsigned long *)0x40021024))

//*****************************************************************************

// 端口A,串口1要用到PORTA 9.10两个引脚

// General-Purpose Input/Outputs (PORTA)

//

//*****************************************************************************

#define GPIO_PORTA       ((volatile unsigned long *)0x40010800)

#define GPIO_PORTA_CRL   (*((volatile unsigned long *)0x40010800))

#define GPIO_PORTA_CRH   (*((volatile unsigned long *)0x40010804))

#define GPIO_PORTA_IDR   (*((volatile unsigned long *)0x40010808))

#define GPIO_PORTA_ODR   (*((volatile unsigned long *)0x4001080C))

#define GPIO_PORTA_BSRR  (*((volatile unsigned long *)0x40010810))

#define GPIO_PORTA_BRR   (*((volatile unsigned long *)0x40010814))

#define GPIO_PORTA_LCKR  (*((volatile unsigned long *)0x40010818))

//*****************************************************************************

//   串口1寄存器

//    USART1-Register

//            

//*****************************************************************************

#define USART1_SR    (*((volatile unsigned long *)0x40013800))

#define USART1_DR    (*((volatile unsigned long *)0x40013804))

#define USART1_BRR   (*((volatile unsigned long *)0x40013808))

#define USART1_CR1   (*((volatile unsigned long *)0x4001380C))

#define USART1_CR2   (*((volatile unsigned long *)0x40013810))

#define USART1_CR3   (*((volatile unsigned long *)0x40013814))

#define USART1_GTPR  (*((volatile unsigned long *)0x40013818))
复制代码


要进行串口通讯,首先要设置时钟,时钟源是什么?PLL还是HSE还是HIS?时钟分频是多少?这些都要设置,不然没法计算波特率,波特率的公式在这就不详细列出了下面是系统初始化,也就是初始化系统时钟:

void SystemInit0 (void)

{  



   unsigned long StartUpCounter = 0, HSEStatus = 0;



     RCC_CR |=0x00000001; ///*!< Set HSION bit */

/*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] and MCO[2:0] bits */

  RCC_CFGR &= (uint32_t)0xF8FF0000;  

  RCC_CR &= (uint32_t)0xFEF6FFFF; // /*!< Reset HSEON, CSSON and PLLON bits */

    RCC_CR &= (uint32_t)0xFFFBFFFF; ///*!< Reset HSEBYP bit */

  RCC_CFGR &= (uint32_t)0xFF80FFFF; ///*!< Reset PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE bits */

    RCC_CIR = 0x00000000;//*!< Disable all interrupts */

   /*!< SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   



  RCC_CR |=0x00010000; // /*!< Enable HSE */   



  /*!< Wait till HSE is ready and if Time out is reached exit */

  do

  {

    HSEStatus = RCC_CR & 0x00020000;

    StartUpCounter++;  

  } while((HSEStatus == 0) && (StartUpCounter != 0x0500));



  if ((RCC_CR & 0x00020000) != 0)

  {

    HSEStatus =0x01;

  }

  else

  {

    HSEStatus =0x00;

  }  



  if (HSEStatus ==0x01)

  {

    RCC_CFGR |=0x00000000; ///*!< HCLK = SYSCLK */



       RCC_CFGR |=0x00000000; ///*!< PCLK2 = HCLK */



       RCC_CFGR |=0x00000000; ///*!< PCLK1 = HCLK */



    RCC_CFGR &=(~(0x00010000 | 0x00020000 | 0x003C0000));   

    RCC_CFGR |= 0x00010000 | 0x00020000 | 0x000C0000;///*!< PLLCLK = (8MHz / 2) * 5 = 20 MHz */



       RCC_CR |= 0x01000000;// /*!< Enable PLL */



        while((RCC_CR & 0x02000000) == 0) // /*!< Wait till PLL is ready */

         {

         }



    RCC_CFGR &=~0x00000003;

    RCC_CFGR |=0x00000002;   ///*!< Select PLL as system clock source */   



      while ((RCC_CFGR &0x0000000C) !=0x08)  ///*!< Wait till PLL is used as system clock source */

    {

    }

  }

  else

  {    while (1)

       {

       }

  }

}

设置好时钟就可以串口初始化了:

void stm32_UsartSetup ()   //串口初始化

{

RCC_APB2ENR|=0x00004000; // enable clock for USART1

RCC_APB2ENR|=0x00000001; //复用功能IO时钟使能

RCC_APB2ENR|=0x00000004; //端口A时钟使能

GPIO_PORTA_CRH&=~(0x00000FF0); // Clear PA9, PA10

GPIO_PORTA_CRH|=0x000000B0; // USART1 Tx (PA9)  alternate output push-pull

GPIO_PORTA_CRH|=0x00000400; // USART1 Rx (PA10) input floating





USART1_BRR=0x00000823;  ////波特率9600/20M

USART1_CR1&=0xFFFFEFFF;  // set Data bits

USART1_CR2&=0xFFFFCFFF; // set Stop bits

USART1_CR1&=0xFFFFFBFF;  //  // set Parity



USART1_CR1|=(0x00000004|0x00000008);      // RX, TX enable

USART1_CR1|=0x00002000; // USART enable

}

    到此串口设置设置完毕,下面我要和PC机通讯了,我要从上位机通过串口助手发送一字节的十六进制数,然后下位机(STM32)返回给PC机所发的一字节数据:

int main()

{

  SystemInit0();

stm32_UsartSetup ();

while(1)

{

   while(USART1->SR&0x00000020)  //等待RXNE置位

   {

       flag=USART1_DR&0xff;

  USART1_DR=flag&0xff;

while((USART1->SR)&0x80==0); //等待发送完毕

while((USART1->SR)&0x40==0);

flag=USART1->SR;

  }                                                                                                            

}

}
复制代码

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

376

主题

1418

帖子

1

粉丝