一、GPIO口的配置
STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个双向IO组成。并且没个IO口均可配置成8种模式(4种输入模式,4种输出模式)。不管配置哪个IO口也不论将其配置成哪种模式(但是配置成哪种模式要看具体应用,参考《中文参考手册》第105页)都可以按以下步骤来进行配置: (1)使能PORTx(x=A~G)时钟
这里就得操作寄存器RCC_APB2ENR(32为寄存器)了
15 ADC3EN 7 IOPFEN 14 13 USART1EN TIM8EN 6 5 IOPEEN IOPDEN 12 SPI1EN 4 IOPCEN 11 TIM1EN 3 IOPBEN 10 ADC2EN 2 IOPAEN 9 ADC1EN 1 保留 8 IOPGEN 0 AFIOEN RCC_APB2ENR的0~15位(06~32位保留)
第2~8分别是使能GPIOA~GPIOG时钟的,只要将其置“1”即可,如
RCC_APB2ENR|=1<<2;就是使能GPIOA的时钟;其余IO口的始终使能一次类推。 (2)对相应的IO模式进行配置,低8位配置GPIOx_CRL;高8位配置GPIOx_CRH 31 30 CNF7[1:0] 23 22 CNF5[1:0] 15 14 CNF3[1:0] 7 6 CNF1[1:0] 29 28 MODE7[1:0] 21 20 MODE5[1:0] 13 12 MODE3[1:0] 5 4 MODE1[1:0] 27 26 CNF6[1:0] 19 18 CNF4[1:0] 11 10 CNF2[1:0] 3 2 CNF0[1:0] 25 24 MODE6[1:0] 17 16 MODE4[1:0] 9 8 MODE2[1:0] 1 0 MODE0[1:0] GPIOx_CRL(x=A~G(端口配置低寄存器x=A?E)
该寄存器用于配置GPIOx的低8位,具体8种模式的配置见《中文参考手册》例如: GPIOD->CRL&=0XFFFFF0FF;GPIOD->CRL|=0X00000300;/PD.2推挽输出;其余IO口的低8位以此类推。 31 30 CNF15[1:0] 23 22 CNF13[1:0] 15 14 CNF11[1:0] 7 6 CNF9[1:0] 29 28 MODE15[1:0] 21 20 MODE13[1:0] 13 12 MODE11[1:0] 5 4 MODE9[1:0] 27 26 CNF14[1:0] 19 18 CNF12[1:0] 11 10 CNF10[1:0] 3 2 CNF8[1:0] 25 24 MODE14[1:0] 17 16 MODE12[1:0] 9 8 MODE10[1:0] 1 0 MODE8[1:0] GPIOx_CRH(端口配置高寄存器x=A?E)
该寄存器用于配置GPIOx的高8位,具体8种模式的配置见《中文参考手册》例如: GPIOA->CRH&=0XFFFFFFF0;;GPIOA->CRH|=0X00000003;//PA8 推挽输出;其余IO口的高8位以此类推。
(3)端口的输入和输出电平配置 15 IDR15 7 IDR7 14 IDR14 6 IDR6 13 IDR13 5 IDR5 12 IDR12 4 IDR4 11 IDR11 3 IDR3 10 IDR10 2 IDR2 9 IDR9 1 IDR1 8 IDR8 0 IDR0
GPIOx_IDR(端口输入数据寄存器x=A?E) 该寄存器配置IO口的0~15位的输入数据,以16位读出。 15 ODR15 7 ODR7 14 ODR14 6 ODR6 13 ODR13 5 ODR5 12 ODR12 4 ODR4 11 ODR11 3 ODR3 10 ODR10 2 ODR2 9 ODR9 1 ODR1 8 ODR8 0 ODR0 GPIOx_ODR(端口输出数据寄存器x=A?E)
该寄存器配置IO口的0~15位的输入初始状态,例如:GPIOA->ODR|=1<<13;//PA13上拉输入
一般GPIO口配置可仿以下两个程序: void KEY_Init(void) {
RCC->APB2ENR|=1<<2; //使能PORTA时钟 GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入 GPIOA->CRL|=0X00000008;
GPIOA->CRH&=0X0F0FFFFF;//PA13,15设置成输入 GPIOA->CRH|=0X80800000; GPIOA->ODR|=1<<13; //PA13上拉,PA0默认下拉 GPIOA->ODR|=1<<15; //PA15上拉 }
void LED_Init(void) {
RCC->APB2ENR|=1<<2; //使能PORTA时钟 RCC->APB2ENR|=1<<5; //使能PORTD时钟 GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000003;//PA8 推挽输出 GPIOA->ODR|=1<<8; //PA8 输出高 GPIOD->CRL&=0XFFFFF0FF;
GPIOD->CRL|=0X00000300;//PD.2推挽输出 GPIOD->ODR|=1<<2; //PD.2输出高 }
二、串口通信
STM32最多可以提供5路串口,其串口配置主要有以下步骤: (1)串口时钟使能
15 ADC3EN 7 IOPFEN 14 13 USART1EN TIM8EN 6 5 IOPEEN IOPDEN 12 SPI1EN 4 IOPCEN 11 TIM1EN 3 IOPBEN 10 ADC2EN 2 IOPAEN 9 ADC1EN 1 保留 8 IOPGEN 0 AFIOEN RCC_APB2ENR的0~15位(16~32位保留) 在寄存器RCC_APB2ENR里的第14位就是对串口1的时钟使能即: RCC_APB2ENR|=1<<14; //使能串口1时钟 , 那么除串口1的时钟使能在RCC_APB2ENR外其余的时钟使能位在寄存器RCC_APB1ENR里,看下表:
31 保留 23 USBEN 15 SPI3EN 7 30 22 I2C2EN 14 SPI2EN 6 保留 29 DACEN 21 I2C1EN 13 28 PWREN 20 UART5EN 12 保留 5 4 TIM7EN TIM6EN 27 26 25 24 BKPEN 保留 CANEN 保留 19 18 17 16 UART4EN UART3EN UART2EN 保留 11 10 9 8 WWDGEN 保留 3 2 1 0 TIM5EN TIM4EN TIM3EN TIM2EN
RCC_APB1ENR
例如:RCC_APB1ENR|=1<<17; //使能串口2时钟 ,其余串口时钟使能以此类推。 (2)串口复位即结束复位
STM32在使用串口时不管当前该串口出于什么状态都先要将其复位,而复位后要将其结束复位。串口复位主要在寄存器RCC_APB1RSTR(串口1的复位)和寄存器 RCC_APB2RSTR(其余串口复位)这两个寄存器如下表 15 ADC3RST 7 IOPFRST 14 13 USART1RST TIM8RST 6 5 IOPERST IOPDRST 12 SPI1RST 4 IOPCRST 11 TIM1RST 3 IOPBRST 10 ADC2RST 2 IOPARST 9 ADC1RST 1 保留 8 IOPGRST 0 AFIORST
RCC_APB2RSTR(APB2外设复位寄存器)
寄存器RCC_APB2RSTR的第14位是进行串口1的复位如:RCC_APB1RSTR|=1<<14; //将串口1复位 ,然后结束复位RCC_APB1RSTR|=~(1<<14); //结束串口1复位 其余串口复位在寄存器 RCC_APB1RSTR里如下表:
29 28 27 26 25 24 保留 DACRST PWRRST BKPRST 保留 CANRST 保留 23 22 21 20 19 18 17 16 USBRST I2C2RST I2C1RST UART5RST UART4RST UART3RST UART2RST 保留 15 14 13 12 11 10 9 8 SPI3RST SPI2RST 保留 WWDGRST 保留 7 6 5 4 3 2 1 0 保留 TIM7RST TIM6RST TIM5RST TIM4RST TIM3RST TIM2TST RCC_APB1RSTR(APB1外设复位寄存器)
如: RCC_APB1RSTR|=1<<17; //复位串口2 RCC_APB1RSTR|=~(1<<17); // 结束串口2复位 ,其余串口复位操作以此类推。
(3)串口波特率设置 31 30 15 7 14 12 11 10 9 8 DIV_Mantissa[11:4] 6 5 4 3 2 1 0 DIV_Mantissa[3:0] DIV_Fraction[3:0] 13 USART_BRR(波特比率寄存器)
该寄存器的15-4位:DIV_Mantissa[11:0]USARTDIV的整数部分,这12位定义了USART分频器除法因子(USARTDIV)的整数部分;3-0位:DIV_Fraction[3:0]USARTDIV的小数部分,这4位定义了USART分频器除法因子(USARTDIV)的小数部分。关于波特率设置在函数 void uart_init(u32 pclk2,u32 bound)里已经设置好,并且封装在usart.c文件里面可以直接调用。 (4)串口控制
STM32的每个串口都有3个控制寄存器(USART_CR1~3)控制,例如USART_CR1如下: 15 保留 7 TXEIE 14 UE 6 TCIE 13 M 5 RXNEIE 12 4 IDLEIE 11 WAKE 3 TE 10 PCE 2 RE 9 PS 1 RWU 8 PEIE 0 SBK USART_CR1(控制寄存器1) 该寄存器32~14位保留,第13位使能串口(任何串口在应用的时候都必需将其置“1”)第12位设置字长,当这位为“0”的时候设置串口位8个字长外加n个停止位,这n个停止位在寄存器USART_CR2中第[13:12]位来决定。PCE为奇偶校验使能位设置为“0”则禁止校验,否则使能校验。PS是交验选择位,设置为“0”则为偶校验,否则为奇校验。PEIE:PE(校验错误)中断使能,该位由软件设置或清除,定义:0(禁止产生中断),1(当USART_SR中的PE为’1’时,产生USART中断)。TXEIE发送缓冲区空中断使能,(手动),定义:0(禁止产生中断),1(当USART_SR中的TXE为’1’时,产生USART中断)。TCIE发送完成中断使能,(手动),定义:0(禁止产生中断)1(当USART_SR中的TC为’1’时,产生USART中断)。RXNEIE接收缓冲区非空中断使能,(手动),定义:0(禁止产生中断),1(当USART_SR中的ORE或者RXNE为’1’时,产生USART中断)。TE为发送使能位,设置为“1”将开启串口的发送功能。RE为接收使能位,用法同TE。
15 保留 7 保留 14 LINEN 6 LBDIE 13 12 STOP[1:0] 5 4 LBDL 保留 11 CLKEN 3 10 CPOL 2 9 CPHA 1 ADD[3:0] 8 LBCL 0
USART_CR2(控制寄存器2)
如:USART1->CR1|=0X200C; //1位停止,无校验位. 0X200C=0010 0000 0000 1100B 设置成使能串口8个字长1个停止位(USART_CR2中[13:12]默认为“0”)禁止校验,禁止校验所有中断,使能发送和接收。 (5)数据发送和接收 15 7 14 6 13 5 12 11 保留 4 3 DR[7:0] 10 2 9 1 8 DR[8] 0 USART_DR(数据寄存器) 发送数据缓存寄存器(向它写数据它会自动发送数据),当接收到数据时则存放接收的数据 (6)串口控制 15 7 TXE TC 14 6 13 保留 5 RXNE 12 4 LDLE 11 3 ORE NE 10 CTS 2 FE 9 LBD 1 PE 8 0 USART_SR 参考程序:
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; // 波特率设置