文档库 最新最全的文档下载
当前位置:文档库 › 牛人的STM32学习笔记(寄存器版本)

牛人的STM32学习笔记(寄存器版本)

牛人的STM32学习笔记(寄存器版本)
牛人的STM32学习笔记(寄存器版本)

一、GPIO口的配置

STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个

双向IO组成。并且没个IO口均可配置成8种模式(4种输入模式,4种输出模式)。不管

配置哪个IO口也不论将其配置成哪种模式(但是配置成哪种模式要看具体应用,参考《中

文参考手册》第105页)都可以按以下步骤来进行配置:

(1)使能PORTx(x=A~G)时钟

这里就得操作寄存器RCC_APB2ENR(32为寄存器)了

15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN

7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留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 29 28 27 26 25 24

CNF7[1:0] MODE7[1:0] CNF6[1:0] MODE6[1:0]

23 22 21 20 19 18 17 16

CNF5[1:0] MODE5[1:0] CNF4[1:0] MODE4[1:0]

15 14 13 12 11 10 9 8

CNF3[1:0] MODE3[1:0] CNF2[1:0] MODE2[1:0]

7 6 5 4 3 2 1 0

CNF1[1:0] MODE1[1:0] CNF0[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 29 28 27 26 25 24

CNF15[1:0] MODE15[1:0] CNF14[1:0] MODE14[1:0]

23 22 21 20 19 18 17 16

CNF13[1:0] MODE13[1:0] CNF12[1:0] MODE12[1:0]

15 14 13 12 11 10 9 8

CNF11[1:0] MODE11[1:0] CNF10[1:0] MODE10[1:0]

7 6 5 4 3 2 1 0

CNF9[1:0] MODE9[1:0] CNF8[1:0] MODE8[1:0]

GPIOx_CRH(端口配置高寄存器x=A…E)

该寄存器用于配置GPIOx的高8位,具体8种模式的配置见《中文参考手册》例如:

GPIOA->CRH&=0XFFFFFFF0;;GPIOA->CRH|=0X00000003;//PA8 推挽输出;其余IO口

的高8位以此类推。

(3)端口的输入和输出电平配置

15 14 13 12 11 10 9 8 IDR15 IDR14 IDR13 IDR12 IDR11 IDR10 IDR9 IDR8

7 6 5 4 3 2 1 0 IDR7 IDR6 IDR5 IDR4 IDR3 IDR2 IDR1 IDR0

GPIOx_IDR(端口输入数据寄存器x=A…E)

该寄存器配置IO口的0~15位的输入数据,以16位读出。

15 14 13 12 11 10 9 8

ODR15 ODR14 ODR13 ODR12 ODR11 ODR10 ODR9 ODR8

7 6 5 4 3 2 1 0

ODR7 ODR6 ODR5 ODR4 ODR3 ODR2 ODR1 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 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN

7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留AFIOEN

RCC_APB2ENR的0~15位(16~32位保留)

在寄存器RCC_APB2ENR里的第14位就是对串口1的时钟使能即:

RCC_APB2ENR|=1<<14; //使能串口1时钟,那么除串口1的时钟使能在RCC_APB2ENR

外其余的时钟使能位在寄存器RCC_APB1ENR里,看下表:

31 30 29 28 27 26 25 24

保留DACEN PWREN BKPEN 保留CANEN 保留

23 22 21 20 19 18 17 16 USBEN I2C2EN I2C1EN UART5EN UART4EN UART3EN UART2EN 保留

15 14 13 12 11 10 9 8 SPI3EN SPI2EN 保留WWDGEN 保留

7 6 5 4 3 2 1 0

保留TIM7EN TIM6EN TIM5EN TIM4EN TIM3EN TIM2EN

RCC_APB1ENR

例如:RCC_APB1ENR|=1<<17; //使能串口2时钟,其余串口时钟使能以此类推。

(2)串口复位即结束复位

STM32在使用串口时不管当前该串口出于什么状态都先要将其复位,而复位后要将其

结束复位。串口复位主要在寄存器RCC_APB1RSTR(串口1的复位)和寄存器

RCC_APB2RSTR(其余串口复位)这两个寄存器如下表

15 14 13 12 11 10 9 8

ADC3RST USART1RST TIM8RST SPI1RST TIM1RST ADC2RST ADC1RST IOPGRST 7 6 5 4 3 2 1 0 IOPFRST IOPERST IOPDRST IOPCRST IOPBRST IOPARST 保留AFIORST

RCC_APB2RSTR(APB2外设复位寄存器)

寄存器RCC_APB2RSTR的第14位是进行串口1的复位如:RCC_APB1RSTR|=1<<14; //将

串口1复位,然后结束复位RCC_APB1RSTR|=~(1<<14); //结束串口1复位

其余串口复位在寄存器RCC_APB1RSTR里如下表:

31 30 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)串口波特率设置

15 14 13 12 11 10 9 8

DIV_Mantissa[11:4]

7 6 5 4 3 2 1 0

DIV_Mantissa[3:0] DIV_Fraction[3:0]

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 14 13 12 11 10 9 8

保留UE M WAKE PCE PS PEIE

7 6 5 4 3 2 1 0 TXEIE TCIE RXNEIE IDLEIE TE RE RWU 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 14 13 12 11 10 9 8

保留LINEN STOP[1:0] CLKEN CPOL CPHA LBCL 7 6 5 4 3 2 1 0

保留LBDIE LBDL 保留ADD[3:0]

USART_CR2(控制寄存器2)

如:USART1->CR1|=0X200C; //1位停止,无校验位. 0X200C=0010 0000 0000 1100B

设置成使能串口8个字长1个停止位(USART_CR2中[13:12]默认为“0”)禁止校验,禁止

校验所有中断,使能发送和接收。

(5)数据发送和接收

15 14 13 12 11 10 9 8

保留DR[8]

7 6 5 4 3 2 1 0

DR[7:0]

USART_DR(数据寄存器)

发送数据缓存寄存器(向它写数据它会自动发送数据),当接收到数据时则存放接收的数据(6)串口控制

15 14 13 12 11 10 9 8

保留CTS LBD

7 6 5 4 3 2 1 0 TXE TC RXNE LDLE ORE NE FE PE

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; // 波特率设置

USART1->CR1|=0X200C; //1位停止,无校验位.

#ifdef EN_USART1_RX //如果使能了接收

//使能接收中断

USART1->CR1|=1<<8; //PE中断使能

USART1->CR1|=1<<5; //接收缓冲区非空中断使能

MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级#endif

}

void USART1_IRQHandler(void)

{

u8 res;

if(USART1->SR&(1<<5))//接收到数据

{

res=USART1->DR;

if((USART_RX_STA&0x80)==0)//接收未完成

{

if(USART_RX_STA&0x40)//接收到了0x0d

{

if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始

else USART_RX_STA|=0x80; //接收完成了

}else //还没收到0X0D

{

if(res==0x0d)USART_RX_STA|=0x40;

else

{

USART_RX_BUF[USART_RX_STA&0X3F]=res;

USART_RX_STA++;

if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收

}

}

}

}

}

以上两个函数已经封装在usart.c中可直接调用

三、外部中断

STM32的每一个IO口都可以作为中断输入,要想把IO口作为中断输入则必须将IO口

设置成上拉/下拉输入或浮空输入(设置成浮空输入时要接上拉或下拉电阻否则可能导致中

断不断触发)。下面总结一下设置IO口为外部中断时的步骤:

(1)将IO口设置成输入模式

这个在第一章总结过,这里不多说。

(2)开启IO口复用时钟,设置IO口与中断线的映射关系

这一步在函数void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM) 中已经封装好可直接调用

这里说一下IO口的复用时钟使能:

15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN

7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留AFIOEN

RCC_APB2ENR

RCC_APB2ENR|=0X01; //使能IO口复用时钟

(3)开启与该IO口相对应的线上中断/事件,并设置触发条件

这一步封装在函数void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM) 中,可以直接调用,例如:Ex_NVIC_Config(GPIO_A,0,RTIR); //设置PA(0)上升沿触发

Ex_NVIC_Config(GPIO_A,13,FTIR);//设置PA(13)下降沿触发

(4)配置中断分组(NVIC)并使能中断

这一步封装在函数void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group) 里面可以直接调用,例如:

MY_NVIC_Init(2,2,EXTI0_IRQChannel,2); //抢占2,子优先级2,组2

这里值得注意的是EXTI0、EXTI1、EXTI2、EXTI3、EXTI4为Line0~Line4

EXTI15_10为Line15~Line10 EXTI9_5为Line9~Line5

(5)编写中断服务函数

例如:void EXTI15_10_IRQHandler(void)

{

delay_ms(10); //消抖

if(KEY0==0) //按键0

{

LED0=!LED0;

}

else if(KEY1==0)//按键1

{

LED1=!LED1;

}

EXTI->PR=1<<13; //清除LINE13上的中断标志位

EXTI->PR=1<<15; //清除LINE15上的中断标志位

}

四、定时计数器中断

STM32共有8个定时计数器,其中TIME1和TIME8是高级定时器,TIME2~TIME5是

通用定时器,TIME6和TIME7是基本定时器,这里以TIME3为例先总结以下定时计数器

的基本用法。

定时计数器TIME3中断的配置步骤:

(1)TIME3时钟使能

31 30 29 28 27 26 25 24

保留DACEN PWREN BKPEN 保留CANEN 保留

23 22 21 20 19 18 17 16 USBEN I2C2EN I2C1EN UART5EN UART4EN UART3EN UART2EN 保留

15 14 13 12 11 10 9 8 SPI3EN SPI2EN 保留WWDGEN 保留

7 6 5 4 3 2 1 0

保留TIM7EN TIM6EN TIM5EN TIM4EN TIM3EN TIM2EN

RCC_APB1ENR

例如:RCC->APB1ENR|=1<<1;//使能TIME3的时钟;

RCC->APB1ENR|=1<<2;//使能TIME4的时钟;

RCC->APB1ENR|=1<<3;//使能TIME5的时钟;

RCC->APB1ENR|=0X01;//使能TIME2的时钟使能;(RCC->APB1ENR|=1<<0;)

其余的一次类推。

15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN

7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留AFIOEN

RCC_APB2ENR

(2)设置TIM3_ARR和TIM3_PSC的值

这两个位分别设置自动重装值及分频系数

15 14 13 12 11 10 9 8

ARR[15:8]

7 6 5 4 3 2 1 0

ARR[7:0]

TIMx_ARR(TIM6和TIM7自动重装载寄存器)

15 14 13 12 11 10 9 8

PSC[15:8]

7 6 5 4 3 2 1 0

PSC[7:0]

TIMx_PSC(TIM6和TIM7预分频器)

(3)设置TIM3_DIER允许更新中断

15 14 13 12 11 10 9 8

保留TDE 保留CC4DE CC3DE CC2DE CC1DE UDE

7 6 5 4 3 2 1 0

保留TIE 保留CC4IE CC3IE CC2IE CC1IE UIE

TIMx_DIER

例如:TIM3->DIER|=1<<0; //允许更新中断

TIM3->DIER|=1<<6; //允许触发中断

(4)允许TIM3工作(使能TIM3)

15 14 13 12 11 10 9 8

保留CKD[1:0]

7 6 5 4 3 2 1 0 ARPE CMS[1:0] DIR OPM URS UDIS CEN

TIMx_CR1

例如:TIM3->CR1|=0x01; //使能定时器3

15 14 13 12 11 10 9 8

保留CC4OF CC3OF CC2OF CC1OF 保留

7 6 5 4 3 2 1 0 BIF TIF COMIF CC4IF CC3IF CC2IF CC1IF UIF

TIMx_SR

该寄存器用来标记当前预定时器相关的各种事件/中断是否发生。

UIF:更新中断标记,当产生更新事件时该位由硬件置’1’。

例如:if(TIM3->SR&0X0001)//溢出中断

(5)TIM3中断分组设置

例如:MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2

直接调用该函数就行

(6)编写中断服务程序

例如:void TIM3_IRQHandler(void)

{

if(TIM3->SR&0X0001)//溢出中断

{

LED1=!LED1;

}

TIM3->SR&=~(1<<0);//清除中断标志位

}

参考程序:void Timerx_Init(u16 arr,u16 psc)

{

RCC->APB1ENR|=1<<1;//TIM3时钟使能

TIM3->ARR=arr; //设定计数器自动重装值//刚好1ms

TIM3->PSC=psc; //预分频器7200,得到10Khz的计数时钟

//这两个东东要同时设置才可以使用中断

TIM3->DIER|=1<<0; //允许更新中断

TIM3->DIER|=1<<6; //允许触发中断

TIM3->CR1|=0x01; //使能定时器3

MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2

}

TIME2的CH2模式2的PWM输出:

脉冲宽度调制模式可以产生一个由寄存器TIMx_ARR确定频率和由寄存器

TIMx_CCRx确定其占空比的PWM波形;

使能定时器:RCC->APB1ENR|=1<<0;//使能TIME2的时钟

选择通道(共4个通道):在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1)或’111’(PWM模式2);

15 14 13 12 11 10 9 8 OC2CE OC2M[2:0] OC2PE OC2FE

IC2F[3:0] IC2PSC[1:0]

CC2S[1:0]

7 6 5 4 3 2 1 0

OC1CE OC1M[2:0] OC1PE OC1FE

CC1S[1:0] IC1F[3:0] IC1PSC[1:0]

TIMx_CCMR1(捕获/比较模式寄存器1)

TIM2->CCMR1|=7<<12; //选择PWM模式2

使能预装载寄存器:必须设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄

存器;

15 14 13 12 11 10 9 8 OC2CE OC2M[2:0] OC2PE OC2FE

IC2F[3:0] IC2PSC[1:0]

CC2S[1:0]

7 6 5 4 3 2 1 0

OC1CE OC1M[2:0] OC1PE OC1FE

IC1F[3:0] IC1PSC[1:0]

CC1S[1:0]

TIMx_CCMR1(捕获/比较模式寄存器1)

TIM2->CCMR1|=1<<11; //使能预装载寄存器

使能自动重装载的预装载寄存器:最后还要设置TIMx_CR1寄存器的ARPE位,(在向

上计数或中心对称模式中)使能自动重装载的预装载寄存器;

15 14 13 12 11 10 9 8

保留CKD[1:0]

7 6 5 4 3 2 1 0 ARPE CMS[1:0] DIR OPM URS UDIS CEN

TIMx_CR1

TIMx_CR1|=1<<7; //使能自动装载的预分频寄存器

设置极性:OCx的极性可以通过软件在TIMx_CCER寄存器中的CCxP位设置,它可以

设置为高电平有效或低电平有效。TIMx_CCER寄存器中的CCxE位控制OCx输出使能;

15 14 13 12 11 10 9 8

保留CC4P CC4E 保留CC3P CC3E

7 6 5 4 3 2 1 0

保留CC2P CC2E 保留CC1P CC1E

TIMx_CCER(捕获/比较使能寄存器)

TIM2->CCER&=0X03;

TIM2->CCMR|=1<<4; // //设置极性并输出时能

void Timerx2_Init(u16 arr,u16 psc)

{

RCC->APB1ENR|=1<<0;//使能TIME2的时钟

TIM3->ARR=arr;//设定计数器自动重装值

TIM3->PSC=psc;//预分频器不分频

TIM2->CCMR1|=7<<12; //选择PWM模式2

TIM2->CCMR1|=1<<11; //使能预装载寄存器

TIM2->CR1|=1<<7; //使能自动装载的预分频寄存器

TIM2->CR1|=1<<0; //使能定时器

// TIM2->CCER=0X3303;

TIM2->CCER|=1<<4; //设置极性并输出时能

}

比如利用TIM3的通道TH3产生PWM输出:

void PWM_Init(u16 arr,u16 psc)

{

RCC->APB1ENR|=1<<1; //TIM3时钟使能

GPIOA->CRL&=0X0FFFFFFF;//PA7输出

GPIOA->CRL|=0XB0000000;//复用功能输出

GPIOA->ODR|=1<<7;//PA7上拉

TIM3->ARR=arr;//设定计数器自动重装值

TIM3->PSC=psc;//预分频器不分频

TIM3->CCMR1|=7<<12; //CH2 PWM2模式

TIM3->CCMR1|=1<<11; //CH2预装载使能

TIM3->CCER|=1<<4; //OC2 输出使能

TIM3->CR1=0x8000; //ARPE使能

TIM3->CR1|=0x01; //使能定时器3

}

其余几个定时器的PWM输出寄存器配置依次类推。

以下例子说明如何在TI1输入的上升沿时捕获计数器的值到TIM1_CCR1寄存器中,步骤如下:

1、使能TIM1时钟:

RCC_APB2ENR 的0~15位(06~32位保留) RCC->APB2ENR|=1<<11; //使能TIME1的时钟 2、选择有效输入端:

TIM1_CCMR1必须.接到TI1 输入,所以写入TIM1_CCMR1寄存器中的CC1S=01,一旦CC1S=01不为00时,通道被配置为输入,并且TIM1_CCMR1 寄存器变.只读。

15 14

13 12

11 10 9 8

OC2CE OC2M[2:0] OC2PE OC2FE CC2S[1:0] IC2F[3:0] IC2PSC[1:0] 7 6 5

4

3 2 1 0 OC1CE

OC1M[2:0] OC1PE OC1FE CC1S[1:0]

IC1F[3:0]

IC1PSC[1:0]

TIM1_CCMR1(捕获/比较模式寄存器1)

TIM1->CCMR 1=0X01; //CC1通道选择输入,IC1映射在TI1上

3、根据输入信号的特点,配置输入滤波器为所需的带宽(输入为TI1时TIM1_CCMRx 寄存器中的ICxF 位)。假设输入信号在最多5 个时钟周期的时间内抖动,我们.配置滤波器的带长于5个时钟周期。因此我们可以(以fDTS 频率)连续采样8次,已确认在TI1上一次真实的边沿变换,即在TIM1_CCMR1寄存器中写入IC1F=0011.

15 14

13 12

11 10 9 8

OC2CE OC2M[2:0] OC2PE OC2FE CC2S[1:0] IC2F[3:0] IC2PSC[1:0] 7 6 5

4

3 2 1 0 OC1CE

OC1M[2:0] OC1PE OC1FE CC1S[1:0]

IC1F[3:0]

IC1PSC[1:0]

TIM1_CCMR1(捕获/比较模式寄存器1) TIM1->CCMR1|=3<<4; //

4、选择TI1 通道的有效转.边沿,在TIM1_CCER 寄存器中写入CC1P=0(即上升沿)。

15

14 13

12 11

10 9 8 保留 CC4P

CC4E 保留 CC3P

CC3E 7

6

5 4 3 2

1 0 保留

CC2P CC2E

保留

CC1P CC1E

TIMx_CCER(捕获/比较使能寄存器) TIM1->CCER&=0<<1; 5、配置输入预分频器。

15 14 13 12 11 10 9 8 ADC3EN

USART1EN TIM8EN

SPI1EN

TIM1EN

ADC2EN

ADC1EN

IOPGEN

7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留 AFIOEN

在本例中,我们希望捕获发生在每一个有效的电平转换时刻,因此预分频器被禁止(写TIM1_CCMR1 寄存器的IC1PS=00)。

15 14 13 12 11 10 9 8 OC2CE OC2M[2:0] OC2PE OC2FE

CC2S[1:0] IC2F[3:0] IC2PSC[1:0]

7 6 5 4 3 2 1 0

OC1CE OC1M[2:0] OC1PE OC1FE

IC1F[3:0] IC1PSC[1:0]

CC1S[1:0]

TIM1_CCMR1(捕获/比较模式寄存器1)

(见第二步)

6、设置TIM1_CCER 寄存器的CC1E=1,允许捕获计数器的值到捕获寄存器中。

15 14 13 12 11 10 9 8

保留CC4P CC4E 保留CC3P CC3E

7 6 5 4 3 2 1 0

保留CC2P CC2E 保留CC1P CC1E

TIMx_CCER(捕获/比较使能寄存器)

TIM1->CCER|=1<<0;

7、如果需要,通过.置TIM1_DIER 寄存器中的CC1IE 位允许相关中断求,通过置TIM1_DIER

寄存器中的CC1DE允许DAM请求。

15 14 13 12 11 10 9 8 保留TDE COMDE CC4DE CC3DE CC2DE CC1DE UDE

7 6 5 4 3 2 1 0 BIE TIE COMIE CC4IE CC3IE CC2IE CC1IE UIE

TIMx_DIER(TIM1和TIM8 DMA/中断使能寄存器)

TIM1->DIER|=1<<1;

TIM1->DIER|=1<<0;

捕获函数:

void Tim1_th1_cap_Init(u16 arr,u16 psc)

{

RCC->APB2ENR|=1<<11; //使能TIME1的时钟

RCC->APB2ENR|=1<<2; //就是使能GPIOA的时钟

RCC->CHL&=0XFFFFFFF0;

RCC->CHL|=0X00000004; //设置PA8为浮空输入

TIM1->ARR=arr;

TIM1->PSC=psc;

TIM1->CCMR1=0X01; //CC1通道选择输入,IC1映射在TI1上

TIM1->CCMR1|=3<<4; //

TIM1->CCER&=0<<1; //上升沿触发

TIM1->CCER|=1<<0; //捕获使能

TIM1->DIER|=1<<1; //允许捕获中断

TIM1->DIER|=1<<0; //允许更新中断

TIM1->CR1|=1<<0; //使能计数器1

MY_NVIC_Init(1,1,TIM1_IRQChannel,2); //抢占1,子1,组2

中断服务程序:

主函数:

五、SPI总线

SPI_CR寄存器的CPOL和CPHA位,能够组合成四种可能的时序关系。CPOL(时钟极性)位控制在没有数据传输时时钟的空闲状态电平,此位对主模式和从模式下的设备都有效。

如果CPOL被清’0’,SCK引脚在空闲状态保持低电平;如果CPOL被置’1’,SCK引脚在空闲

状态保持高电平。

如果CPHA(时钟相位)位被置’1’,SCK时钟的第二个边沿(CPOL位为0时就是下降沿,CPOL

位为’1’时就是上升沿)进行数据位的采样,数据在第二个时钟边沿被锁。如果CPHA位被清’0’,SCK时钟的第一边沿(CPOL位为’0’时就是下降沿,CPOL位为’1’时就是上升沿)进行

数据位采样,数据在第一个时钟边沿被锁存。

空闲SCK CPOL(时钟极性)CPHA(时钟相位)

0 0

1 1

第二个时钟边沿下降沿采样0 1

第二个时钟边沿上升沿采样 1 1

第一个时钟边沿下降沿采样0 0

第一个时钟边沿上升沿采样 1 0

SPI配置成主模式:

1、使能SPI时钟和PORTA时钟:

15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN

7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留AFIOEN

RCC_APB2ENR的0~15位(06~32位保留)

RCC->APB2ENR|=1<<2; //PORTA时钟使能

RCC->APB2ENR|=1<<12; //SPI1时钟使能

2、开全双工模式并软件管理NSS:

15 14 13 12 11 10 9 8 BIDIMODE BIDIOE CRCEN CRCNEXT DFF RXONLY SSM SSI

7 6 5 4 3 2 1 0 LSBFIRST SPE BR[2:0] MSTR CPOL CPHA

SPI控制寄存器1(SPI_CR1)

SPI1->CR1|=0<<10;//全双工模式

SPI1->CR1|=1<<9;

SPI1->CR1|=1<<8; //软件nss管理

3、设置SPI为主机并设置数据帧格式:

15 14 13 12 11 10 9 8 BIDIMODE BIDIOE CRCEN CRCNEXT DFF RXONLY SSM SSI

7 6 5 4 3 2 1 0 LSBFIRST SPE BR[2:0] MSTR CPOL CPHA

SPI控制寄存器1(SPI_CR1)

SPI1->CR1|=1<<2; //SPI主机

SPI1->CR1|=0<<11;//8bit数据格式

4、设置时钟极性和相位极性:

15 14 13 12 11 10 9 8 BIDIMODE BIDIOE CRCEN CRCNEXT DFF RXONLY SSM SSI

7 6 5 4 3 2 1 0 LSBFIRST SPE BR[2:0] MSTR CPOL CPHA

SPI控制寄存器1(SPI_CR1)

SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1

SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1

5、传输速率和LSBFIRST帧格式设置:

15 14 13 12 11 10 9 8 BIDIMODE BIDIOE CRCEN CRCNEXT DFF RXONLY SSM SSI

7 6 5 4 3 2 1 0 LSBFIRST SPE BR[2:0] MSTR CPOL CPHA

SPI控制寄存器1(SPI_CR1)

SPI1->CR1|=7<<3; //Fsck=Fcpu/256

SPI1->CR1|=0<<7; //MSBfirst

6、使能SPI设备:

15 14 13 12 11 10 9 8 BIDIMODE BIDIOE CRCEN CRCNEXT DFF RXONLY SSM SSI

7 6 5 4 3 2 1 0 LSBFIRST SPE BR[2:0] MSTR CPOL CPHA

SPI控制寄存器1(SPI_CR1)

SPI1->CR1|=1<<6; //SPI设备使能

参考程序:

void SPIx_Init(void)

{

RCC->APB2ENR|=1<<2; //PORTA时钟使能

RCC->APB2ENR|=1<<12; //SPI1时钟使能

//这里只针对SPI口初始化

GPIOA->CRL&=0X000FFFFF;

GPIOA->CRL|=0XBBB00000;//PA5.6.7复用

GPIOA->ODR|=0X7<<5; //PA5.6.7上拉

SPI1->CR1|=0<<10;//全双工模式

SPI1->CR1|=1<<9; //软件nss管理

SPI1->CR1|=1<<8;

SPI1->CR1|=1<<2; //SPI主机

SPI1->CR1|=0<<11;//8bit数据格式

SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1

SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1

SPI1->CR1|=7<<3; //Fsck=Fcpu/256

SPI1->CR1|=0<<7; //MSBfirst

SPI1->CR1|=1<<6; //SPI设备使能

SPIx_ReadWriteByte(0xff);//启动传输

}

SPI读写数据程序(注意全双工同时读写):

//SPIx读写一个字节

//TxData:要写入的字节

//返回值:读到的字节

u8 SPIx_ReadWriteByte(u8 Txdata)

{

u8 temp=0;

while((SPI->SR&1<<1)==0)

//SPI->SR&1<<1(发送缓冲区为空);(SPI->SR&1<<1)==0(发送缓冲区为空不成立即//发送缓冲区不为空)则一直判断等待发送缓冲区为空(跳出while循环)才发送数据{

temp++;

if(temp>300)

return 0; //若经判断发送缓冲区不为空则返回值“0”

}

SPI->DR=Txdata; //若发送缓冲区为空则发送数据

temp=0;

while((SPI->SR&1<<0)==0)

//(SPI->SR&1<<0)==0(判断接收缓冲区是否为空)若为空则接收数据

{

temp++;

if(temp>300)

return 0;

}

return SPI->DR;

}

六、DS18B20温度传感器

用单片机控制温度传感器DS18B20进行温度采集主要进行一下步骤:

(1)复位:首先我们必须对DS18B20芯片进行复位,复位就是由控制器(单片机)给DS18B20单总线至少480uS的低电平信号。当18B20接到此复位信号后则会在15~60uS后回发一个芯片的存在脉冲。

void DS18B20_Rst(void)

{

DS18B20_IO_OUT(); //讲PA0设置成输出状态

DS18B20_DQ_OUT=0; //拉低DQ(PA0接DQ)

delay_us(750); //拉低750us

DS18B20_DQ_OUT=1; / /DQ=1 释放数据线讲DQ交给1820

delay_us(15); / /15US

}

(2)存在脉冲:在复位电平结束之后,控制器应该将数据单总线拉高,以便于在15~60uS 后接收存在脉冲,存在脉冲为一个60~240uS的低电平信号。至此,通信双方已经达成了基本的协议,接下来将会是控制器与18B20间的数据通信。如果复位低电平的时间不足或是单总线的电路断路都不会接到存在脉冲,在设计时要注意意外情况的处理。

u8 DS18B20_Check(void) //j检测ds18b20是否存在

{

u8 retry=0;

DS18B20_IO_IN();//SET PA0 INPUT

while (DS18B20_DQ_IN&&retry<200)

{

retry++;

delay_us(1);

};

if(retry>=200)return 1;

else retry=0;

while (!DS18B20_DQ_IN&&retry<240)

{

retry++;

delay_us(1);

};

if(retry>=240)return 1;

return 0;

}

(3)控制器发送ROM指令:双方打完了招呼之后最要将进行交流了,ROM指令共有5条,每一个工作周期只能发一条,ROM指令分别是读ROM数据、指定匹配芯片、跳跃ROM、芯片搜索、报警芯片搜索。ROM指令为8位长度,功能是对片内的64位光刻ROM进行操作。其主要目的是为了分辨一条总线上挂接的多个器件并作处理。诚然,单总线上可以同时挂接多个器件,并通过每个器件上所独有的ID号来区别,一般只挂接单个18B20芯片时可以跳过ROM指令(注意:此处指的跳过ROM指令并非不发送ROM指令,而是用特有的一条“跳过指令”)。控制器发送存

储器操作指令:在ROM指令发送给18B20之后,紧接着(不间断)就是发送存储器操作指令了。操作指令同样为8位,共6条,存储器操作指令分别是写RAM数据、读RAM数据、将RAM数据复制到EEPROM、温度转换、将EEPROM中的报警值复制到RAM、工作方式切换。存储器操作指令的功能是命令18B20作什么样的工作,是芯片控制的关键。

void DS18B20_Start(void)// ds1820 start convert

{

DS18B20_Rst();

DS18B20_Check();

DS18B20_Write_Byte(0xcc); // skip rom 跳过ROM

DS18B20_Write_Byte(0x44); // convert 温度转换命令

}

(4)执行或数据读写:一个存储器操作指令结束后则将进行指令执行或数据的读写,这个操作要视存储器操作指令而定。如执行温度转换指令则控制器(单片机)必须等待18B20执行其指令,一般转换时间为500uS。如执行数据读写指令则需要严格遵循18B20的读写时序来操作。数据的读写方法将有下文有详细介绍。若要读出当前的温度数据我们需要执行两次工作周期,第一个周期为复位、跳过ROM指令、执行温度转换存储器操作指令、等待500uS温度转换时间。紧接着执行第二个周期为复位、跳过ROM指令、执行读RAM的存储器操作指令、读数据(最多为9个字节,中途可停止,只读简单温度值则读前2个字节即可)。其它的操作流程也大同小异,在此不多介绍。

STM32库函数操作和寄存器操作

STM32库函数操作和寄存器操作 首先,两个都是C语言。从51过渡过来的话,就先说寄存器操作。每个MCU都有自己的寄存器,51是功能比较简单的一种,相应的寄存器也比较少,我们常用的就那么几个,像P0 P1 SMOD TMOD之类的,这些存在于标准头文件reg.h里面,因为少,所以大家就直接这么去操作了,每一位对应的意义随便翻一下手册就看得到,甚至做几个小项目就记的很清楚了。所以做51开发的时候大多数都是直接操作寄存器。 到了STM32,原理一样,也是有自己的寄存器,但是作为一款ARM 内核的芯片,功能多了非常多,寄存器自然也就多了很多,STM32的手册有一千多页,这时候想去像51那样记住每个寄存器已经不现实了,所以ST的工程师就给大家提供了库函数这么一个东西。这是个神器。库函数里面把STM32的所有寄存器用结构体一一对应并且封装起来,而且提供了基本的配置函数。我们要去操作配置某个外设的时候不需要再去翻眼花缭乱的数据手册,直接找到库函数描述拿来就可以用,这样就能把精力放在逻辑代码的开发上,而不是去费力的研究一个芯片的外设要怎么配置寄存器才能驱动起来。简单讲就是这些了,库函数是为了让开发者从大量繁琐的寄存器操作中脱离出来的一个文件包,在使用一个外设的时候让开发者直接去调用相应的驱动函数而不是自己去翻手册一个一个配置寄存器。有人说用库函数掌握不到芯片的精髓,见仁见智了。熟悉一款芯片是在不断的开发使用中逐渐了解并掌握的,调试的过程中会遇到很多问题,会要求我们去跟踪相关寄存器的状态,在整个框架都已经建立起来的基础上再去对照手册做具体到寄存器每一位的分析,代码对照现象,很快就能积累起来经验,祝成功。

STM32单片机GPIO寄存器的功能解析

STM32单片机GPIO寄存器的功能解析 1、GPIO的寄存器按照功能可以分为以下几类: A、配置寄存器 B、数据寄存器 C、位寄存器 D、锁定寄存器 2、对于GPIO端口,每个端口有16个引脚,每个引脚的模式由寄存器的四个位控制,每四位又分为两位控制引脚配置(CNFy[1:0]),两位控制引脚的模式及最高速度(MODEy [1:0]),其中y表示第y个引脚。配置GPIO引脚模式的一共有两个寄存器,CRH是高寄存器,用来配置高8位引脚,还有CRL配置低八位引脚。 3、端口位设置\清除寄存器(GPIOx_BSRR) 一个引脚y的输出数据由GPIOx_BSRR寄存器位的2个位来控制分别为BRy (Bit Reset y)和BSy (Bit Set y),BRy位用于写1清零,使引脚输出低电平,BSy位用来写1置1,使引脚输出高电平。而对这两个位进行写零都是无效的。 4、Cortex-M3有32根地址线,所以它的 寻址空间大小为2 bit=4GB。ARM公司设计时,预先把这4GB的寻址空间大致地分配好了。它把地址从0x4000 0000至0x5FFF FFFF(512MB )的地址分配给片上外设。 5、stm32f10x.h这个文件中重要的内容就是把STM32的所有寄存器进行地址映射。如同51单片机的头文件一样,stm32f10x.h像一个大表格,我们在使用的时候就是通过宏定义进行类似查表的操作。 6、STM32总线有AHB总线、APB2总线、APB1总线 7、时钟系统。 A、从时钟频率来说分为告诉时钟和低速时钟,高速时钟是提供给芯片主体时钟,而低速时钟只是提供给芯片中的RTC及独立看门狗使用。 B、从芯片角度来说,时钟源分为内部时钟与外部时钟源,内部时钟是在芯片内部RC振

STM32f103寄存器说明

CRC寄存器 (一种算法,用以确认发送过程中是否出错)数据寄存器:CRC_DR 可读写,复位值:0xFFFF FFFF; 独立数据寄存器:CRC_IDR 临时存放任何8位数据; 控制寄存器:CRC_CR 只零位可用,用于复位CRC,对其写1复位,由硬件清零; PWR电源控制(控制和管理电源) 电源控制寄存器:PWR_CR 控制选择系统的电源 电源控制/状态寄存器:PWR_CSR 睡眠或待机模式电源控制 BKP备份寄存器(用以控制和管理备份数据) 备份数据寄存器x:BKP_DRx (x = 1 … 10) 10个16位数据寄存器用以存储用户数据 RTC时钟校准寄存器:BKP_RTCCR 控制实时时钟的运行 备份控制寄存器:BKP_CR 控制选择清除备份数据的类型

备份控制/状态寄存器:BKP_CSR 对侵入事件的控制 RCC寄存器(时钟的选择、复位、分频) 时钟控制寄存器(RCC_CR) 各时钟状态显示 时钟配置寄存器(RCC_CFGR) 时钟分频 时钟中断寄存器(RCC_CIR) 控制就绪中断使能与否 APB2外设复位寄存器(RCC_APB2RSTR) APB1外设复位寄存器(RCC_APB1RSTR) 复位APB各功能寄存器 AHB外设时钟使能寄存器(RCC_AHBENR) AHB时钟使能控制 APB2外设时钟使能寄存器(RCC_APB2ENR) APB1外设时钟使能寄存器(RCC_APB1ENR) APB1时钟使能控制 备份域控制寄存器(RCC_BDCR) 备份域时钟控制 控制/状态寄存器(RCC_CSR) 复位标志寄存器 AHB外设时钟复位寄存器(RCC_AHBRSTR) 复位以太网MAC模块 时钟配置寄存器2(RCC_CFGR2) 时钟选择与分频

STM32使用BSRR和BRR寄存器快速操作

STM32使用BSRR和BRR寄存器快速操作 GPI0端口STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSR和GPIOx_BRF寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置“或置“ 0。“ GPIOx_BSRR勺高16位中每一位对应端口x的每个位,对高16位中的某位置“狈『端口x的对应位被清“0;“寄存器中的位置“0, “则对它对应的位不起作 用。 GPIOx_BSRR的氐16位中每一位也对应端口x的每个位,对低16位中的某位置“1则“它对应的端口位被置“1;“寄存器中的位置“0,“则对它对应的端口不起作用。 简单地说GPIOx_BSR的高16位称作清除寄存器,而GPIOx_BSR的低氐16 位称作设置寄存器。另一个寄存器GPIOx_BRfl只有低16位有用,与GPIOx_BSR 的高16位具有相同功能。 举个例子说明如何使用这两个寄存器和所体现的优势。例如GPIOE的16个IO都被设置成输出,而每次操作仅需要改变低8位的数据而保持高8位不变,假设新的8 位数据在变量Newdata 中, 这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数GPIO_SetBits和GPIO_ResetBits使用了这两个寄存器操作端口。 上述要求可以这样实现: GPI0_SetBits(GPI0E, Newdata & 0xff); GPI0_ResetBits(GPI0E, (~Newdata & 0xff)); 也可以直接操作这两个寄存器: GPI0E->BSRR = Newdata & 0xff; GPI0E->BRR = ~Newdata & 0xff; 当然还可以一次完成对8位的操作:

stm32 BKP寄存器操作操作寄存器+库函数

stm32 BKP 寄存器操作操作寄存器+库函数 BKP 是BACKUP 的缩写,stm32f103RCTE 的内部配备了10 个16 位宽度 的BKP 寄存器。在主电源切断或系统产生复位时间时,BKP 寄存器仍然可以 在备用电源的支持下保持其内容。BKP 在实际应用中可以存入重要数据,防止 被恶意查看,或用于断电等。本例实现对BKP 寄存器的读写操作,和入侵检 测和处理。主程序中写入寄存器后,依次打印出10 个BKP 寄存器数据,然后 触发GPIOC13 的入侵中断(输入低电平),在中断中打印出入侵事件发生后的 寄存器内容(复位为0 )。直接操作寄存器用到的寄存器描述如下:备份数据 寄存器x(BKP_DRx) (x = 1 10):低16 位[15:0]有效,用来写入或读出备份数据。备份控制寄存器(BKP_CR):低两位有效。TPAL[1]:侵入检测TAMPER 引脚有效电平(TAMPER pin active level)0:侵入检测TAMPER 引脚上的高电平会清除所有数据备份寄存器(如果TPE 位为1) 1:侵入检测TAMPER 引脚 上的低电平会清除所有数据备份寄存器(如果TPE 位为1)TPE[0]:启动侵入检 测TAMPER 引脚(TAMPER pin enable)0:侵入检测TAMPER 引脚作为通用IO 口使用1:开启侵入检测引脚作为侵入检测使用备份控制/状态寄存器 (BKP_CSR): TIF[9]:侵入中断标志(Tamper interrupt flag) 0:无侵入中断1:产生侵入中断当检测到有侵入事件且TPIE 位为1 时,此位由硬件置1。通过向CTI 位 写1 来清除此标志位(同时也清除了中断)。如果TPIE 位被清除,则此位也会被 清除。TEF[8]:侵入事件标志(Tamper event flag) 0:无侵入事件1:检测到侵入事件当检测到侵入事件时此位由硬件置1。通过向CTE 位写1 可清除此标 志位TPIE[2]:允许侵入TAMPER 引脚中断(TAMPER pin interrupt enable)0:禁止侵入检测中断1:允许侵入检测中断(BKP_CR 寄存器的TPE 位也必须被置1)注

(整理)基于STM32的LCD操作

嵌入式系统》课程报告 基于 STM32的 LCD 操作 组长:曾昭智 组员:邓 宁、张小扬、牛洪澄 光电学院 电信 2班、3 班 2014.05.29 姓名 学院 班级 完成日期

目录 1、原理方案(功能框图介绍) (1) 2、电路连线及资源分配. (2) 3、所用主要器件或模块说明. (3) 4、程序流程图. (4) 5、调试心得. (5) 6、源代码 (6)

1.TFT-LCD 原理 1.1 TFT-LCD 简介 TFT-LCD即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display 。TFT-LCD与无源TN-LCD、STN-LCD 的简单 矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD也被叫做真彩液晶显示器。 上一节介绍了OLED模块,这一节,我们给大家介绍ALIENTEK TFTLC模D 块,该模块有如下特点: 1,2.4 '/2.8 '两种大小的屏幕可选。 2,320×240的分辨率。 3,16位真彩显示。 4,自带触摸屏,可以用来作为控制输入。 5,通用的接口,除了ALIENTEK MiniSTM32开发板,该液晶模块还可以使用在优异特、STMSK、Y 红牛等开发板上。 本节,我们以 2.8 寸的ALIENTEKT FTLCD模块为例介绍,该模块采用的是显尚光电的DST2001PHT FTLCD,DST2001PH的控制器为ILI9320 ,采用26 万色的TFTLCD 屏,分辨率为320×240,采用16 位的80并口。 1.2 80 并口 ALIENTEK TFTLCD 模块采用80并口口方与外部链接,采用16位数据线(低了速度太慢,用彩色就没什么效果了)。该模块的80并口有如下一些信号线:CS:TFTLCD 片选信号。 WR:向TFTLCD 写入数据。 RD:从TFTLCD 读取数据。 D[15:0] :16位双向数据线。 RST:硬复位TFTLCD 。 RS:命令/数据标志(0,读写命令;1,读写数据)。 TFTLCD 模块的RST信号线和OLED 模块一样,也是直接接到STM32 的复位脚上,并 不由软件控制,这样可以省下来一个IO 口。另外我们还需要一个背光控制线来控制TFTLCD 的背光。所以,我们总共需要的IO 口数目为21 个。 1.3 ILI9320 模块的控制器为ILI9320 ,该控制器自带显存,其显存总大小为172820 (240*320*18/8 ),即18位模式(26万色)下的显存量。模块的16位数据线与显寸的对应关系为565 方式,如下图所示: 1.4 GRAM显示方向设置

STM32_IO口操作

1、不使用库函数的IO口操作 Systick 部分内容属于NVIC控制部分,一共有4个寄存器 SysTick_CTRL, 0xE000E010 -- 控制寄存器默认值:0x0000 0004 SysTick_LOAD, 0xE000E014 -- 重载寄存器默认值:0x0000 0000 SysTick_VAL, 0xE000E018 -- 当前值寄存器默认值:0x0000 0000 SysTick_CALIB, 0xE000E01C -- 校准值寄存器默认值:0x0002328 SysTick_CTRL 寄存器内有4个bit具有意义 第0位:ENABLE,Systick 使能位(0:关闭Systick功能;1:开启Systick功能) 第1位:TICKINT,Systick 中断使能位(0:关闭Systick中断;1:开启Systick中断) 第2位:CLKSOURCE,Systick时钟源选择(0:使用HCLK/8 作为Systick时钟;1:使用HCLK 作为系统时钟) 第16位:COUNTFLAG,Systick计数比较标志 IO口的位操作实现 该部分代码实现对STM32各个IO口的位操作,包括读入和输出。当然在这些函数调用之前,必须先进行IO口时钟的使能和IO口功能定义。此部分仅仅对IO口进行输入输出读取和控制。代码如下: #define BITBAND(addr,bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 55

STM32中使用GPIO的总结超强

STM32 GPIO使用 操作步骤: 使能GPIO对应的外设时钟 例如://使能GPIOA、GPIOB、GPIOC对应的外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOC , ENABLE); 声明一个GPIO_InitStructure结构体 例如: GPIO_InitTypeDef GPIO_InitStructure; 选择待设置的GPIO管脚 例如:/* 选择待设置的GPIO 7、8、9管脚位,中间加“|”符号*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; 4. 设置选中GPIO管脚的速率 例如:/* 设置选中GPIO管脚的速率为最高速率2MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //最高速率2MHz GPIO5. 设置选中管脚的模式*/ 设置选中GPIO管脚的模式为开漏输出模式/* 例如://开漏输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIOX

中指定的参数初始化外设6. 根据GPIO_InitStructureGPIOC */ GPIO_InitStructure中指定的参数初始化外设根据例如:/* 1 / 16 GPIO_Init(GPIOC, &GPIO_InitStructure); 7.其他应用 例:将端口GPIOA的 10、15脚置1(高电平) GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15); 例:将端口GPIOA的 10、15脚置0(低电平) GPIO_ResetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15); GPIO寄存器: 寄存器描述 端口配置低寄存器CRL 端口配置高寄存器CRH 端口输入数据寄存器IDR 端口输出数据寄存器ODR 端口位设置BSRR /复位寄存器 端口位复位寄存器BRR 端口配置锁定寄存器LCKR 事件控制寄存器EVCR

STM32的寄存器操作

STM32的寄存器操作和C51的操作有很大的不同。 要操作STM32可以通过库函数操作,也可直接操作寄存器。 下面分析一下寄存器的操作,以控制PE4脚输出高低电平为例: 首先找到GPIOE的寄存器基地址,如下图:(STM32F4xx中文参考手册.pdf) 找到GPIOE的基地址为:0x4002 1000 我们要操作PE4脚,首先找到BSRR位操作寄存器,如下图 BSRR寄存器偏移地址为:0x18 由于我我们要操作PE4,即操作BSRR寄存器的第4位。 下面编写代码: 首先定义一个指向uint32_t型的指针,之后将该指针指向BSRR寄存器地址:

0x4002 1018 = 0x4002 1000 + 0x0000 00018 此时要操作BSRR寄存器,直接向*p赋值就可以了,如下图: 该代码即可实现PE4脚的高低电平输出。 假如不加延时,如下图: 系统也可正常运行,但在这两行处打断点调试,会发现无法进入,分析原因是两行代码中间无延时,实际运行时几乎可以忽略该代码的操作,所以编译器在编译时自动优化了,此时我们只需要在声明变量的时候为其指明__IO类型变量(volatile)即可,如下图: 上面的例子从最基本的寄存器分析操作STM32的,下面来分析下官方库函数是如何操作寄存器的。 首先定义GPIO寄存器组,通过结构体将寄存器组封包,如下图:

由于以上寄存器地址是连续的,所以可以分在一个结构体中 然后定义GPIOE寄存器组 这里的GPIOE_BASE为GPIOE寄存器的基地址:0x4002 1000 定义了GPIO_TypeDef类型指针GPIOE,并指向了GPIOE寄存器的基地址。此时我们要操作PE4脚状态只需要操作GPIOE->BSRR就可以了, 其它寄存器的操作参考上面的分析即可实现。

Stm32之寄存器列表

学习STM32,官方提供一个库,但如果刚入手的话,肯定连功能都不太清楚,所以用不太习觉得还是操作寄存器来的直接,所以就整理了STM32的大部分寄存器共大家参考。版权归 基本上都是103的,其中107的RCC,USB,和以太网等一些不太重要的没有,但大部分都有我只是把数据手册中的寄存器整理了一下方便大家看。如果有什么不对的,请通知我,也好联系方式:qq 526083029 小树 PWR电源相关寄存器 PWR_CR(电源控制寄存器) 31302928272625242322212019181716 保留 1514131211109876543210保留DBP PLS[2:0]PVDE CSBF CWUF PDDS LPDS 8位:DBP取消后备区域写保护。复位值为0。定义:0为禁止写入,1为允许写入。注:如果rtc时钟是HSE/128,必须保持为1 7-5位:PVD电源电压检测器的电压阀值。定义:000(2.2v),001(2.3v),010(2.4v),011(2.5v),100(2.6v),101(2.7v),110(2.8v),4位:PVDE电源电压检测器(PVD)使能。定义:0(禁止PVD),1(开启PVD) 3位:CSBF清除待机位(始终输出为0)定义:0(无功效),1(清除SBF待机位(写) 2位:CWUF清除唤醒位(始终输出为0)定义:0(无功效),1(2个系统时钟周期后清除WUF唤醒位(写) 1位:PDDS掉电深睡眠(与LPDS位协同操作)定义:0(当CPU进入深睡眠时进入停机模式,调压器状态由LPDS位控制),1(CPU进入深睡眠时进入待机模0位:LPDS深睡眠下的低功耗(PDDS=0时,与PDDS位协同操作)定义:0(在待机模式下电压调压器开启),1(在待机模式下电压调压器处于低功耗模式 PWR_CSR(电源控制/状态寄存器) 31302928272625242322212019181716 保留 1514131211109876543210保留EWUP保留PVDO SBF WUF 8位:EWUP使能WKUP引脚。定义:0(WKUP为通用IO),1(用于待机唤醒模式,WKUP引脚被强置为输入下拉的配置(WKUP引脚上的上升沿将系统从待机模 注:复位时清除这一位 2位:PVDO-PVD输出(当PVD被PVDE位使能后该位才有效)定义:0(VDD/VDDA高于PLS[2-0]选定的PVD阀值),1(VDD/VDDA低于PLS[2-0]选定的PVD阀值 注:在待机模式下PVD被停止,因此,待机模式后或复位后,直到设置PVDE位之前,该位为0 1位:SBF待机标志位(该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的CSBUF位清除)定义:0(不在待机 0位:WUF唤醒标志(该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的CWUF位清除) 定义:0(没有唤醒事件),1(在WKUP引脚上发生唤醒事件或出现RTC脑中事件) 注:当WKUP引脚已经是高电平时,在(通过设置EWUP位)使能WKUP引脚时,会检测到一个额外事件 BKP——DRx(x=1...10)(备份数据寄存器) 1514131211109876543210 15-0位:备份数据由用户来写数据。注:BKP——DRx寄存器不会被系统复位,电源复位,待机唤醒所复位 它可以由备份域复位来复位或(如果入侵检测引脚TAMPER功能被开启时)由浸入引脚事件复位 BKP_RTCCR(RTC时钟校准寄存器) 1514131211109876543210

使用BSRR和BRR寄存器直接操作STM32的IO端口

STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置'1'或置'0'。 GPIOx_BSRR的高16位中每一位对应端口x的每个位,对高16位中的某位置'1'则端口x的对应位被清'0';寄存器中的位置'0',则对它对应的位不起作用。 GPIOx_BSRR的低16位中每一位也对应端口x的每个位,对低16位中的某位置'1'则它对应的端口位被置'1';寄存器中的位置'0',则对它对应的端口不起作用。 简单地说GPIOx_BSRR的高16位称作清除寄存器,而GPIOx_BSRR的低16位称作设置寄存器。另一个寄存器GPIOx_BRR只有低16位有效,与GPIOx_BSRR的高16位具有相同功能。 举个例子说明如何使用这两个寄存器和所体现的优势。例如GPIOE的16个IO都被设置成输出,而每次操作仅需要改变低8位的数据而保持高8位不变,假设新的8位数据在变量Newdata 中, 这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数GPIO_SetBits()和GPIO_ResetBits()使用了这两个寄存器操作端口。 上述要求可以这样实现: GPIO_SetBits(GPIOE, Newdata & 0xff); GPIO_ResetBits(GPIOE, (~Newdata & 0xff)); 也可以直接操作这两个寄存器: GPIOE->BSRR = Newdata & 0xff; GPIOE->BRR = ~Newdata & 0xff; 当然还可以一次完成对8位的操作: GPIOE->BSRR = (Newdata & 0xff) | (~Newdata & 0xff)<<16; 从最后这个操作可以看出使用BSRR寄存器,可以实现8个端口位的同时修改操作。 如果不是用BRR和BSRR寄存器,则上述要求就需要这样实现: GPIOE->ODR = GPIOE->ODR & 0xff00 | Newdata; 使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。

STM32寄存器操作举例

如何用寄存器的方法操作STM32 这个文章是摘自阿莫论坛,觉得写得很不错,就收藏下来了,整理成文档,希望更多的人能看到 既然我们要操作IO 口,当然就要看IO口相关的知识。打开STM3210x参考手册.pdf ,我的目的只是操作GPIO 所以我只需要将第五章看完就OK了。章节比较多,懒得看,根据一般的经验(楼主,你缺经验了吧?),不说多 就AVR 和PIC 而已。操作IO一般是两个步骤,第一,操作IO控制寄存器,设置IO为输出,第二就是送数据。 那么很明显,只可能是GPIOx_CRL GPIOx_CRH ,GPIOx_ODR 三个寄存器会有想要 仔细阅读这几个寄存器的介绍后知道,GPIOx_CRL 是控制PIN 0-7 的属性的,GPIOx_CRH 控制PIN 8-15,ODR寄存器 当然就是输出数据了,将数据送到这里就行了。 然后,这几个寄存器的地址是多少?首先看stm32f103ve.pdf 这个是官方的datasheet、,看第四章,Mmeory Mapping 为什么看这章?会英文都能猜到吧?,看PORTB 的地址是0x40010C00 - 0x40010FFF ,这个就是基地址了。基地址 加上偏移量就能找到具体的寄存器。 例如我需要操作GPIOB_CRL 的偏移为00H ,(看STM3210x参考手册.pdf)ODR 寄存器的偏移为0CH 那么很自然得出 GPIOB_CRL = 0x40010C00 GPIOB_ODR = 0x40010C0C 怎么验证我的结论正确?先看keil 给的头文件\Keil\ARM\INC\ST\STM32F10x\stm32f10x_map.h #define PERIPH_BASE ((u32)0x40000000) #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) 这样怎么算都能算出0x40010C00 出来吧??ODR 寄存器同理 为了点亮LED ,我需要将PB5 (也就是GPIOB5)设置为输出,并且ODR相应的位写入1 ,看资料得出MODE5 是 bit 20 21 控制的,CNF5 是bit 22,23 MODE5应该设置10(0x2) 选择2MHZ 输出,CNF5 选择00(0x0),通用推挽模式,于是将这个值写入(*volatile unsigned long)0x40010C00 = (2<<20) | (0<<22); // 为简单起见,不管其他位了

牛人的STM32学习笔记(寄存器版本)

一、GPIO口的配置 STM32的DGPIO口最多可以有7组(GPIOa~GPIOg),而每一组GPIO口均有16个 双向IO组成。并且没个IO口均可配置成8种模式(4种输入模式,4种输出模式)。不管 配置哪个IO口也不论将其配置成哪种模式(但是配置成哪种模式要看具体应用,参考《中 文参考手册》第105页)都可以按以下步骤来进行配置: (1)使能PORTx(x=A~G)时钟 这里就得操作寄存器RCC_APB2ENR(32为寄存器)了 15 14 13 12 11 10 9 8 ADC3EN USART1EN TIM8EN SPI1EN TIM1EN ADC2EN ADC1EN IOPGEN 7 6 5 4 3 2 1 0 IOPFEN IOPEEN IOPDEN IOPCEN IOPBEN IOPAEN 保留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 29 28 27 26 25 24 CNF7[1:0] MODE7[1:0] CNF6[1:0] MODE6[1:0] 23 22 21 20 19 18 17 16 CNF5[1:0] MODE5[1:0] CNF4[1:0] MODE4[1:0] 15 14 13 12 11 10 9 8 CNF3[1:0] MODE3[1:0] CNF2[1:0] MODE2[1:0] 7 6 5 4 3 2 1 0 CNF1[1:0] MODE1[1:0] CNF0[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 29 28 27 26 25 24 CNF15[1:0] MODE15[1:0] CNF14[1:0] MODE14[1:0] 23 22 21 20 19 18 17 16 CNF13[1:0] MODE13[1:0] CNF12[1:0] MODE12[1:0] 15 14 13 12 11 10 9 8 CNF11[1:0] MODE11[1:0] CNF10[1:0] MODE10[1:0] 7 6 5 4 3 2 1 0 CNF9[1:0] MODE9[1:0] CNF8[1:0] MODE8[1:0] GPIOx_CRH(端口配置高寄存器x=A…E) 该寄存器用于配置GPIOx的高8位,具体8种模式的配置见《中文参考手册》例如: GPIOA->CRH&=0XFFFFFFF0;;GPIOA->CRH|=0X00000003;//PA8 推挽输出;其余IO口 的高8位以此类推。

stm32寄存器

(一种算法,用以确认发送过程中是否出错)数据寄存器:CRC_DR 可读写,复位值:0xFFFF FFFF; 独立数据寄存器:CRC_IDR 临时存放任何8位数据; 控制寄存器:CRC_CR 只零位可用,用于复位CRC,对其写1复位,由硬件清零; PWR电源控制(控制和管理电源) 电源控制寄存器:PWR_CR 控制选择系统的电源 电源控制/状态寄存器:PWR_CSR 睡眠或待机模式电源控制 BKP备份寄存器(用以控制和管理备份数据) 备份数据寄存器x:BKP_DRx (x = 1 … 10) 10个16位数据寄存器用以存储用户数据 RTC时钟校准寄存器:BKP_RTCCR 控制实时时钟的运行 备份控制寄存器:BKP_CR 控制选择清除备份数据的类型 备份控制/状态寄存器:BKP_CSR 对侵入事件的控制

(时钟的选择、复位、分频) 时钟控制寄存器(RCC_CR) 各时钟状态显示 时钟配置寄存器(RCC_CFGR) 时钟分频 时钟中断寄存器(RCC_CIR) 控制就绪中断使能与否 APB2外设复位寄存器(RCC_APB2RSTR) APB1外设复位寄存器(RCC_APB1RSTR) 复位APB各功能寄存器 AHB外设时钟使能寄存器(RCC_AHBENR) AHB时钟使能控制 APB2外设时钟使能寄存器(RCC_APB2ENR) APB1外设时钟使能寄存器(RCC_APB1ENR) APB1时钟使能控制 备份域控制寄存器(RCC_BDCR) 备份域时钟控制 控制/状态寄存器(RCC_CSR) 复位标志寄存器 AHB外设时钟复位寄存器(RCC_AHBRSTR) 复位以太网MAC模块 时钟配置寄存器2(RCC_CFGR2) 时钟选择与分频

STM32的FLASH操作

关于STM32的FLASH操作 说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置、芯片ID、自举程序等等。当然,FLASH还可以用来装数据。 FLASH分类 根据用途,STM32片内的FLASH分成两部分:主存储块、信息块。 主存储块用于存储程序,我们写的程序一般存储在这里。 信息块又分成两部分:系统存储器、选项字节。 系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。这个区域由芯片厂写入BootLoader,然后锁死,用户是无法改变这个区域的。 选项字节存储芯片的配置信息及对主存储块的保护信息。 FLASH的页面 STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。页面典型的用途就是用于按页擦除FLASH。从这点来看,页面有点像通用FLASH的扇区。 STM32产品的分类 STM32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。 小容量产品主存储块1-32KB,每页1KB。系统存储器2KB。 中容量产品主存储块64-128KB,每页1KB。系统存储器2KB。 大容量产品主存储块256KB以上,每页2KB。系统存储器2KB。 互联型产品主存储块256KB以上,每页2KB。系统存储器18KB。 对于具体一个产品属于哪类,可以查数据手册,或根据以下简单的规则进行区分:STM32F101xx、STM32F102xx 、STM32F103xx产品,根据其主存储块容量,一定是小容量、中容量、大容量产品中的一种,STM32F105xx、STM32F107xx 是互联型产品。 互联型产品与其它三类的不同之处就是BootLoader的不同,小中大容量产品的BootLoader只有2KB,只能通过USART1进行ISP,而互联型产品的BootLoader 有18KB,能通过USAT1、4、CAN等多种方式进行ISP。小容量产品、中容量产品的BootLoader与大容量产品相同。 关于ISP与IAP ISP(In System Programming)在系统编程,是指直接在目标电路板上对芯片进行编程,一般需要一个自举程序(BootLoader)来执行。ISP也有叫ICP(In Circuit Programming)、在电路编程、在线编程。 IAP(In Application Programming)在应用中编程,是指最终产品出厂后,由最终用户在使用中对用户程序部分进行编程,实现在线升级。IAP要求将程序分成两部分:引导程序、用户程序。引导程序总是不变的。IAP也有叫在程序中编程。ISP与IAP的区别在于,ISP一般是对芯片整片重新编程,用的是芯片厂的自举程序。而IAP只是更新程序的一部分,用的是电器厂开发的IAP引导程序。综

Stm32f103寄存器整理

313029282726252423222120191817 16151413121110987654321 DBP PVDE CSBF CWUF PDDS LPDS 313029282726252423222120191817 16151413121110987654321 EWUP PVDO SBF WUF 151413121110987654321 15-0位:备份数据由用户来写数据。注:BKP——DRx寄存器不会被系统复位,电源复位,待机唤醒所复位 它可以由备份域复位来复位或(如果入侵检测引脚TAMPER功能被开启时)由浸入引脚事件复位 BKP BKP__RTCCR RTCCR((RTC RTC时钟校准寄存器时钟校准寄存器时钟校准寄存器)) 0位:WUF唤醒标志(该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的CWUF位清除) 定义:0(没有唤醒事件),1(在WKUP引脚上发生唤醒事件或出现RTC脑中事件) 注:当WKUP引脚已经是高电平时,在(通过设置EWUP位)使能WKUP引脚时,会检测到一个额外事件 BKP——DRx BKP——DRx((x =1......101010)()()(备份数据寄存器备份数据寄存器备份数据寄存器)) 注:复位时清除这一位 2位:PVDO-PVD输出(当PVD被PVDE位使能后该位才有效)定义:0(VDD/VDDA高于PLS[2-0]选定的PVD阀值),1(VDD/VDDA低于PLS[2-0]选定的PVD阀值) 注:在待机模式下PVD被停止,因此,待机模式后或复位后,直到设置PVDE位之前,该位为0 1位:SBF待机标志位(该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的CSBUF位清除)定义:0(不在待机)1(已待机)3位:CSBF清除待机位(始终输出为0)定义:0(无功效),1(清除SBF待机位(写) 2位:CWUF清除唤醒位(始终输出为0)定义:0(无功效),1(2个系统时钟周期后清除WUF唤醒位(写) 1位:PDDS掉电深睡眠(与LPDS位协同操作)定义:0(当CPU进入深睡眠时进入停机模式,调压器状态由LPDS位控制),1(CPU进入深睡眠时进入待机模式)8位:EWUP使能WKUP引脚。定义:0(WKUP为通用IO),1(用于待机唤醒模式,WKUP引脚被强置为输入下拉的配置(WKUP引脚上的上升沿将系统从待机模式唤醒)0位:LPDS深睡眠下的低功耗(PDDS=0时,与PDDS位协同操作)定义:0(在待机模式下电压调压器开启),1(在待机模式下电压调压器处于低功耗模式) PWR PWR__CSR CSR((电源控制电源控制//状态寄存器状态寄存器)) 保留 保留保留7-5位:PVD电源电压检测器的电压阀值。定义:000(2.2v),001(2.3v),010(2.4v),011(2.5v),100(2.6v),101(2.7v),110(2.8v),111(2.9v)8位:DBP取消后备区域写保护。复位值为0。定义:0为禁止写入,1为允许写入。注:如果rtc时钟是HSE/128,必须保持为1 4位:PVDE电源电压检测器(PVD)使能。定义:0(禁止PVD),1(开启PVD) PWR PWR__CR CR((电源控制寄存器电源控制寄存器)) 保留 保留PLS[2:0]PWR PWR电源相关寄存器电源相关寄存器

STM32使用BSRR和BRR寄存器快速操作GPIO端口方法说明

STM32使用BSRR和BRR寄存器快速操作GPIO端口STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置'1'或置'0'。 GPIOx_BSRR的高16位中每一位对应端口x的每个位,对高16位中的某位置'1'则端口x 的对应位被清'0';寄存器中的位置'0',则对它对应的位不起作用。 GPIOx_BSRR的低16位中每一位也对应端口x的每个位,对低16位中的某位置'1'则它对应的端口位被置'1';寄存器中的位置'0',则对它对应的端口不起作用。 简单地说GPIOx_BSRR的高16位称作清除寄存器,而GPIOx_BSRR的低16位称作设置寄存器。另一个寄存器GPIOx_BRR只有低16位有效,与GPIOx_BSRR的高16位具有相同功能。 举个例子说明如何使用这两个寄存器和所体现的优势。例如GPIOE的16个IO都被设置成输出,而每次操作仅需要改变低8位的数据而保持高8位不变,假设新的8位数据在变量Newdata中, 这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数GPIO_SetBits()和GPIO_ResetBits()使用了这两个寄存器操作端口。 上述要求可以这样实现: GPIO_SetBits(GPIOE, Newdata & 0xff); GPIO_ResetBits(GPIOE, (~Newdata & 0xff)); 也可以直接操作这两个寄存器: GPIOE->BSRR = Newdata & 0xff;

GPIOE->BRR = ~Newdata & 0xff; 当然还可以一次完成对8位的操作: GPIOE->BSRR = (Newdata & 0xff) | (~Newdata & 0xff)<<16; 从最后这个操作可以看出使用BSRR寄存器,可以实现8个端口位的同时修改操作。 如果不是用BRR和BSRR寄存器,则上述要求就需要这样实现: GPIOE->ODR = GPIOE->ODR & 0xff00 | Newdata; 使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。 比如希望快速地对GPIOE的位7进行翻转,则可以: GPIOE->BSRR = 0x80; // 置'1' GPIOE->BRR = 0x80; // 置'0' 如果使用常规'读-改-写'的方法: GPIOE->ODR = GPIOE->ODR | 0x80; // 置'1' GPIOE->ODR = GPIOE->ODR & 0xFF7F; // 置'0' 有人问是否BSRR的高16位是多余的,请看下面这个例子: 假如你想在一个操作中对GPIOE的位7置'1',位6置'0',则使用BSRR非常方便:

基于寄存器操作的STM32高级定时器TIM1的四路PWM输出程序讲解

经过一天的努力,终于把stm32 tim1的四路pwm输出搞了出来,为了使大家快速的用起tim1,打算写这篇文档与大家分享。 stm32 tim1功能丰富。针对pwm输出与tim2只有细小的差别,之前在网上找了一些网友的程序,发现大部分都是基于库文件写的,不能对tim1的pwm输出有深层次的理解,个人认为一个合格的程序员,想要最大程度的用好一个片子的话还是要针对寄存器直接操作,完全了解定时器的运行过程,可以对片子的结构有一定的了解。 高级控制定时器(TIM1 和TIM8) 由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动。它适合多种用途,包含测量输入信号的脉冲宽度( 输入捕获) ,或者产生输出波形( 输出比较、PWM、嵌入死区时间的互补PWM等)。使用定时器预分频器和RCC 时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调节。 高级控制定时器(TIM1 和TIM8) 和通用定时器(TIMx) 是完全独立的,它们不共享任何资源。 请读者仔细阅读一下信息: 脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM 模式1) 或’111’(PWM 模式2) ,能够独立地设置每个OCx输出通道产生一路PWM。必须通过设置TIMx_CCMRx寄存器的OCxPE位使能相应的预装载寄存器,最后还要设置TIMx_CR1 寄存器的ARPE 位,( 在向上计数或中心对称模式中)使能自动重装载的预装载寄存器。仅当发生一个更新事件的时候,预装载寄存器才能被传送到影子寄存器,因此在计数器开始计数之前,必须通过设置TIMx_EGR寄存器中的UG位来初始化所有的寄存器。OCx的极性可以通过软件在TIMx_CCER寄存器中的CCxP位设置,它可以设置为高电平有效或低电平有效。OCx的输出使能通过(TIMx_CCER和TIMx_BDTR寄存器中)CCxE、CCxNE、MOE、OSSI和OSSR 位的组合控制。详见TIMx_CCER寄存器的描述。在PWM模式(模式1或模式2) 下,TIMx_CNT 和TIMx_CCRx始终在进行比较,( 依据计数器的计数方向)以确定是否符合TIMx_CCRx≤TIMx_CNT或者TIMx_CNT≤TIMx_CCRx。根据TIMx_CR1 寄存器中CMS位的状态,定时器能够产生边沿对齐的PWM信号或中央对齐的PWM信号。 根据以上信息的提示,我们可以归纳出寄存器操作的步骤: (1)使能相应的定时器时钟线。 (2)配置tim1四路pwm输出引脚为复用功能输出。 (3)配置tim1的分频比和计数装载值。 (4)配置相应通道的pwm输出模式和使能预装载。 (5)打开自动重装载预装载允许位。 (6)根据需要选择向上或者是向下计数模式。 (7)打开相应通道的输出使能。 (8)配置各通道的占空比。 (9)开启开启OC和OCN。 (10)最后使能定时器1. 关于分频比和计数装载值的选择: Tim1的最大时钟频率为72M,假设我们想得到一个频率为4KHZ,占空比0~100%步进为1的pwm。根据计数器的时钟频率(CK_CNT) 等于f CK_PSC/( PSC[15:0]+1)。因为占空比0~100%步进为1,所以我们把计数值设为100.比较值可以设为0~100之间,实现占空比的调节。计数器的时钟频率(CK_CNT)应为4KHZ X 100=400KHZ。所以PSC = 179。ARR=100。有不明白的请看手册。

相关文档