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

更新时间:2024-06-08 13:15:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

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

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 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 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 保留 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<<1; //使能TIME3的时钟; RCC->APB1ENR|=1<<2; //使能TIME4的时钟; RCC->APB1ENR|=1<<3; //使能TIME5的时钟; RCC->APB1ENR|=0X01;//使能TIME2的时钟使能;(RCC->APB1ENR|=1<<0;) 其余的一次类推。

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 (2)设置TIM3_ARR和TIM3_PSC的值 这两个位分别设置自动重装值及分频系数 15 7 14 6 13 5 12 11 ARR[15:8] 4 3 ARR[7:0] 10 2 9 1 8 0 TIMx_ARR(TIM6和TIM7自动重装载寄存器) 15 7 14 6 13 5 12 11 PSC[15:8] 4 3 PSC[7:0] 10 2 9 1 8 0

TIMx_PSC(TIM6和TIM7预分频器)

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

15 14 保留 TDE 7 6 保留 TIE 13 12 保留 CC4DE 5 4 保留 CC4IE 11 CC3DE 3 CC3IE 10 CC2DE 2 CC2IE 9 CC1DE 1 CC1IE 8 UDE 0 UIE TIMx_DIER 例如:TIM3->DIER|=1<<0; //允许更新中断 TIM3->DIER|=1<<6; //允许触发中断 (4)允许TIM3工作(使能TIM3)

15 7 ARPE 14 6 CMS[1:0] 13 12 保留 5 4 DIR 11 3 OPM 10 2 URS 9 8 CKD[1:0] 1 0 UDIS CEN

TIMx_CR1 例如:TIM3->CR1|=0x01; //使能定时器3 15 7 BIF 14 保留 6 TIF 13 5 COMIF 12 CC4OF 4 CC4IF 11 CC3OF 3 CC3IF 10 CC2OF 2 CC2IF 9 CC1OF 1 CC1IF 8 保留 0 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 OC2CE 7 OC1CE 14 13 OC2M[2:0] IC2F[3:0] 6 5 OC1M[2:0] IC1F[3:0] 12 4 11 10 OC2PE OC2FE IC2PSC[1:0] 3 2 OC1PE OC1FE IC1PSC[1:0] 9 8 CC2S[1:0] 1 0 CC1S[1:0] TIMx_CCMR1(捕获/比较模式寄存器1) TIM2->CCMR1|=7<<12; //选择PWM模式2

使能预装载寄存器:必须设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄存器; 15 OC2CE 7 OC1CE 14 13 OC2M[2:0] IC2F[3:0] 6 5 OC1M[2:0] IC1F[3:0] 12 4 11 10 OC2PE OC2FE IC2PSC[1:0] 3 2 OC1PE OC1FE IC1PSC[1:0] 9 8 CC2S[1:0] 1 0 CC1S[1:0]

TIMx_CCMR1(捕获/比较模式寄存器1) TIM2->CCMR1|=1<<11; //使能预装载寄存器

使能自动重装载的预装载寄存器:最后还要设置TIMx_CR1寄存器的ARPE位,(在向上计数或中心对称模式中)使能自动重装载的预装载寄存器;

15 7 ARPE 14 6 CMS[1:0] 13 12 保留 5 4 DIR 11 3 OPM 10 2 URS 9 8 CKD[1:0] 1 0 UDIS CEN

TIMx_CR1

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

设置极性:OCx的极性可以通过软件在TIMx_CCER寄存器中的CCxP位设置,它可以设置为高电平有效或低电平有效。TIMx_CCER寄存器中的CCxE位控制OCx输出使能;

15 保留 7 保留 14 6 13 CC4P 5 CC2P 12 CC4E 4 CC2E 11 保留 3 保留 10 2 9 CC3P 1 CC1P 8 CC3E 0 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时钟:

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位保留) RCC->APB2ENR|=1<<11; //使能TIME1的时钟 2、选择有效输入端:

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

15 OC2CE 7 OC1CE 14 13 OC2M[2:0] IC2F[3:0] 6 5 OC1M[2:0] IC1F[3:0] 12 4 11 10 OC2PE OC2FE IC2PSC[1:0] 3 2 OC1PE OC1FE IC1PSC[1:0] 9 8 CC2S[1:0] 1 0 CC1S[1:0] TIM1_CCMR1(捕获/比较模式寄存器1)

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

3、根据输入信号的特点,配置输入滤波器为所需的带宽(输入为TI1时TIM1_CCMRx寄存器中的ICxF位)。假设输入信号在最多5 个时钟周期的时间内抖动,我们.配置滤波器的带长于5个时钟周期。因此我们可以(以fDTS 频率)连续采样8次,已确认在TI1上一次真实的边沿变换,即在TIM1_CCMR1寄存器中写入IC1F=0011. 15 OC2CE 7 OC1CE 14 13 OC2M[2:0] IC2F[3:0] 6 5 OC1M[2:0] IC1F[3:0] 12 4 11 10 OC2PE OC2FE IC2PSC[1:0] 3 2 OC1PE OC1FE IC1PSC[1:0] 9 8 CC2S[1:0] 1 0 CC1S[1:0]

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

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

14 6 13 CC4P 5 CC2P 12 CC4E 4 CC2E 11 保留 3 保留 10 2 9 CC3P 1 CC1P 8 CC3E 0 CC1E TIMx_CCER(捕获/比较使能寄存器) TIM1->CCER&=0<<1; 5、配置输入预分频器。

在本例中,我们希望捕获发生在每一个有效的电平转换时刻,因此预分频器被禁止(写TIM1_CCMR1 寄存器的IC1PS=00)。 15 OC2CE 7 OC1CE 14 13 OC2M[2:0] IC2F[3:0] 6 5 OC1M[2:0] IC1F[3:0] 12 4 11 10 OC2PE OC2FE IC2PSC[1:0] 3 2 OC1PE OC1FE IC1PSC[1:0] 9 8 CC2S[1:0] 1 0 CC1S[1:0]

TIM1_CCMR1(捕获/比较模式寄存器1) (见第二步)

6、设置TIM1_CCER 寄存器的CC1E=1,允许捕获计数器的值到捕获寄存器中。 15 保留 7 保留 14 6 13 CC4P 5 CC2P 12 CC4E 4 CC2E 11 保留 3 保留 10 2 9 CC3P 1 CC1P 8 CC3E 0 CC1E

TIMx_CCER(捕获/比较使能寄存器) TIM1->CCER|=1<<0; 7、如果需要,通过.置TIM1_DIER 寄存器中的CC1IE 位允许相关中断求,通过置TIM1_DIER寄存器中的CC1DE允许DAM请求。

15 保留 7 BIE 14 TDE 6 TIE 13 COMDE 5 COMIE 12 CC4DE 4 CC4IE 11 CC3DE 3 CC3IE 10 CC2DE 2 CC2IE 9 CC1DE 1 CC1IE 8 UDE 0 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 0 1 第二个时钟边沿下降沿采样 第二个时钟边沿上升沿采样 第一个时钟边沿下降沿采样 第一个时钟边沿上升沿采样

SPI配置成主模式:

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

CPOL(时钟极性) 0 1 0 1 0 1 CPHA(时钟相位) 1 1 0 0 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位保留)

RCC->APB2ENR|=1<<2; //PORTA时钟使能 RCC->APB2ENR|=1<<12; //SPI1时钟使能 2、开全双工模式并软件管理NSS: 15 14 BIDIMODE BIDIOE 7 6 LSBFIRST SPE 13 CRCEN 5 12 11 CRCNEXT DFF 4 3 BR[2:0] 10 RXONLY 2 MSTR 9 SSM 1 CPOL SSI 8 0 CPHA

SPI控制寄存器1(SPI_CR1) SPI1->CR1|=0<<10;//全双工模式 SPI1->CR1|=1<<9; SPI1->CR1|=1<<8; //软件nss管理 3、设置SPI为主机并设置数据帧格式: 15 14 BIDIMODE BIDIOE 7 6 LSBFIRST SPE 13 CRCEN 5 12 11 CRCNEXT DFF 4 3 BR[2:0] 10 RXONLY 2 MSTR 9 SSM 1 CPOL SSI 8 0 CPHA

Void IIC_ASK(void)

{ IIC_SCL=0; SDA_OUT(); IIC_SDA=0; Delay_us(4); IIC_SCL=1; Delay_us(4); IIC_SCL=0; }

void IIC_NASK(void) {

IIC_SCL=0; SDA_OUT(); IIC_SDA=1; Delay_us(4); IIC_SCL=1; Delay_us(4); IIC_SCL=0; }

本文来源:https://www.bwwdw.com/article/ld56.html

Top