运用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;
}
}
}
复制代码 |