牛人的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 IIC 学习笔记总结

STM32系列IIC学习笔记经验总结一、各寄存器内容与组织:控制、地址匹配、数据、状态、时钟控制、上升沿控制

二、IIC协议及STM32的master实现 EVENT后的第一个符号表示事件发生后对应的标志位的状态,着重看7位地址的通信;

三、基础知识(主要讨论起主机模式,从机模式的配置与使用可类比) 1.默认工作在从机模式,产生起始信号后自动转为主机模式,产生终止信号或仲裁失权后自动转为从机模式;起止信号由主 机模式下的软件实现,地址也只能由主机发送,响应信号由接收器发出(软件实现),要注意区别主机、从机、发送机、接收机; 2.数据通信的直接通道,SDA LineShift RegisterDRMemory(数据寄存器与存储器直接的数据交换发生在DMA模式, 另外若从机在SDA接收到的是地址则直接会与地址寄存器比较,而不会送入数据寄存器) 3.主机产生时钟信号,一串数据总是以起始于start信号,终止于stop信号,一旦SDA线上产生start位信号,主机模 式便被选中;9个寄存器的功能分配简单明了:I2C_CR2主要配置时钟与模块中断及DMA使能位,I2C_CR1则主要产生Start等控制信号,I2C_SR2主要是MSL、TRA和BUSY标志位,I2C_SR1则是其他事件的标志位,接下来就是存储数据的I2C_DR,时钟设置的I2C_CC4R和I2C_TRISE,地址匹配的I2C_OAR1和I2C_OAR2; 4.主机模式必要操作序列:外围时钟输入最少2M(标准模式)、4M(快速模式) 1)配置I2C_CR2寄存器以产生正确时序; 2)配置时钟控制寄存器I2C_CCR; 3)配置上升时间寄存器I2C_TRISE; 4)配置I2C_CR1寄存器以使能接口电路; 5)配置I2C_CR1寄存器,置位START位以产生起始信号; 5.时序具体解析 1)Start信号,置位I2C_CR1的START位以产生起始信号(在总线空闲时,即I2C_SR2的BUSY清零),使转为主机模式(置位I2C_SR2的MSL);在主机模式下,置位START位会在当前字节传输完成后产生一个重启ReStart信号;一旦Start信号送出,I2C_SR1的SB位会由硬件置位并产生中断(前提是ITEVFEN位被置位,貌似文档有误,我认为应是IC2_SR2的ITEVTEN位),然后需要读SR1和写DR以清零SB(这也符合操作时序); 2)从机地址发送,7位模式下,地址字节一旦送出,I2C_SR1的ADDR位会由硬件置位并产生中断(前提是ITEVFEN 置位),然后主机等待读取SR1和SR2以清零ADDR(稍微符合,读SR2貌似饶了一步);7位模式下,地址字节最低位若是0则说明主机要进入发送模式,若是1则是接收模式;I2C_SR2的TRA表示主机在发送模式还是接收模式; 3)主机发送模式,地址送出且ADDR清零后,主机会将DR中数据发送到SDA line(当然经过Shift Register),主机会等到第一个数据写入DR(EV8_1阶段),若收到响应脉冲,SR1中的TxE位会置位(前提是ITEVFEN和ITBUFEN已置位);在最后一个字节传输结束前的传输过程中,若TxE置位且某数据字节没有写入DR,BTF会置位直到(硬件清零)该数据字节被写入到DR,这个过程中SCL会一直被拉低; 4)主机发送模式关闭通信,最后一个字节被写入DR,CR1的STOP位要由软件置位而产生停止信号,接口自动转为从机模式(MSL清零);置位Stop位即对应于EV8_2事件; 5)主机接收模式,地址送出且ADDR清零后,主机会进入接收模式,接口会从SDA line中读数据到DR中(同样经过Shift Register);每个字节接收后的操作序列为,产生应答信号(前提是CR1的ACK位置位),RxNE位置位并产生中断(前提是SR2的ITEVFEN和ITBUFEN置位);在最后一个字节传输结束前的传输过程中,若RxNE 置位且某数据未从DR中读取,BTF会置位直到(硬件清零)该数据字节被读出,这个过程SCL会一直被拉低; 6)主机接收模式关闭通信,收到最后一个字节后会发送NACK信号给从机,从机收到NACK会释放总线(SDA和SCL),此时主机便可发送一个Stop或Restart信号;在读完倒数第二个字节后(RxNE中断后),要清零ACK 位以产生NACK应答,要置位STOP/START位以产生Stop/Restart信号;在单字节数据接收状况,NACK 要在ADDR清零前(EV6)设置,STOP信号要在ADDR清零后配置;Stop信号产生后,主机自动进入从机模式(SR2的MSL清零); 7)最后一字节数据接收的ACK响应前若RxNE清零(ACK清零与Stop请求)没有完成,则建议采取以下步骤以确保ACK位在最后一字节数据接收前被清零,STOP位在最后一字节数据接受完后(没有附加数据)被置位: (1)2字节的数据接收:等到ADDR=1;清零ACK,置位POS;清零ADDR;等到BTF=1(数据1在DR,

STM32学习笔记

STM32学习笔记整理 端口复用配置过程 引脚具体可以复用为啥功能,参考芯片手册STM32F103ZET6.Pdf 具体每个引脚配置成什么模式,参考STM32中文参考手册,第八章,通用IO和复用。NVIC中断

假定设置中断优先级组为2,然后设置 中断3(RTC中断)的抢占优先级为2,响应优先级为1。中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。 那么这3个中断的优先级顺序为:中断7>中断3>中断6 特别说明: 一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。 首先,系统运行后先设置中断优先级分组。调用函数: void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); 整个系统执行过程中,只设置一次中断分组。 然后,中断初始化函数 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化NVIC寄存器 结构体内容NVIC_InitTypeDef typedef struct {

MINI-STM32 开发板入门教程.

MINI-STM32 开发板入门教程(一) 开发环境建立及其应用 我们常用的 STM32 开发编译环境为 Keil 公司的 MDK (Microcontroller Development Kit) 和 IAR 公司的 EWARM. 在这里我们提供了比较稳定的新版本编译软件下载: MDK3.50 点击此处下载 EWARM 5.40 点击此处下载 限于篇幅, 在我们的教程里面将先以 MDK 下的一个例子来介绍如何使用 MDK 进行嵌入式 应用开发. MDK 安装与配置: 基于 MDK 下的开发中基本的过程: (1) 创建工程; (2) 配置工程; (3) 用 C/C++ 或者汇编语言编写源文件; (4) 编译目标应用程序 (5) 修改源程序中的错误 (6) 测试链接应用程序 ---------------------------------------------------------------- (1) 创建一个工程: 在 uVision 3 主界面中选择 "Project" -> "New uVision Project" 菜单项, 打开一个标准对话框选择好你电脑中的保存目录后, 输入一个你的工程名字后点确认.我们的工程中建了一个名字叫 "NewProject" 的工程. 从设备库中选择目标芯片, 我们的 MINI-STM32 开发板使用的是 STM32F103V8T6, 因此选 中 STMicrocontroller 下对应的芯片: ARM 32-bit Cortex-M3 Microcontroller, 72MHz, 64kB Flash, 20kB SRAM, PLL, Embedded Internal RC 8MHz and 32kHz, Real-Time Clock, Nested Interrupt Controller, Power Saving Modes, JTAG and SWD,

STM32学习笔记

输入模式初始化GPIOE2,3,4 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PORTA,PORTE时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); ③PE.2.3.4端口配置:GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; ④设置成(上拉)输入:GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; ⑤GPIO_Init(GPIOE, &GPIO_InitStructure); 输出模式初始化 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PB,PE端口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); ③3LED0-->PB.5 端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; ④设置(推挽)输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ⑤设置IO口速度为50MHz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ⑥说明初始化哪个端口GPIO_Init(GPIOB, &GPIO_InitStructure); 在LED灯试验中初始为高电平灭GPIO_SetBits(GPIOB,GPIO_Pin_5); 再初始化相同发输出模式时③④⑤可省略例如(经实验初始化恰好为不同IO口相同IO序号③可省略,应该不规范吧) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数; 2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。 3,头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。 4,他并不是C自带的,可以不用。 5,调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h 这个头文件。

STM32入门教程

前言 一天入门STM32,仅一天的时间,是否有真的这么快。不同的人对入门的理解不一样,这篇一天入门STM32的教程,我们先对入门达成一个共识,如果你有异议,一天入门不了,请不要较真,不要骂街,保持一个工程师该有的修养,默默潜心学习,因为你还有很大的上升空间。 我眼中的入门:(前提是你学过51单片机和C语言) 1、知道参考官方的什么资料来学习,而不是陷入一大堆资料中无从下手。 2、知道如何参考官方的手册和官方的代码来独立写自己的程序,而不是一味的看到人家写的代码就觉得人家很牛逼。 3、消除对STM32的恐惧,消除对库开发的恐惧,学习是一个快乐而富有成就感的过程。

第1章一天入门STM32 本章参考资料:《STM32中文参考手册》《CM3权威指南CnR2》 学习本章时,配合《STM32中文参考手册》GPIO章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。 1.151与STM32简介 51是嵌入式学习中一款入门级的精典MCU,因其结构简单,易于教学,且可以通过串口编程而不需要额外的仿真器,所以在教学时被大量采用,至今很多大学在嵌入式教学中用的还是51。51诞生于70年代,属于传统的8位单片机,如今,久经岁月的洗礼,既有其辉煌又有其不足。现在的市场产品竞争激烈,对成本极其敏感,相应地对MCU的要求也更苛刻:功能更多,功耗更低,易用界面和多任务。面对这些要求,51现有的资源就显得得抓襟见肘了。所以无论是高校教学还是市场需求,都急需一款新的MCU来为这个领域注入新的活力。 基于这市场的需求,ARM公司推出了其全新的基于ARMv7架构的32位Cortex-M3微控制器内核。紧随其后,ST(意法半导体)公司就推出了基于Cortex-M3内核的MCU—STM32。STM32凭借其产品线的多样化、极高的性价比、简单易用的库开发方式,迅速在众多Cortex-M3MCU中脱颖而出,成为最闪亮的一颗新星。STM32一上市就迅速占领了中低端MCU市场,受到了市场和工程师的无比青睐,颇有星火燎原之势。 作为一名合格的嵌入式工程师,面对新出现的技术,我们不是充耳不闻,而是要尽快吻合市场的需要,跟上技术的潮流。如今STM32的出现就是一种趋势,一种潮流,我们要做的就是搭上这趟快车,让自己的技术更有竞争力。 1.1.151与STM32架构的区别 我们先普及一个概念,单片机(即MCU)里面有什么。一个人最重要的是大脑,身体的各个部分都在大脑的指挥下工作。MCU跟人体很像,简单来说是由一个最重要的内核加其他外设组成,内核就相当于人的大脑,外设就如人体的各个功能器官。 下面我们来简单介绍下51和STM32的结构。 1.51系统结构 51系统结构框图

stm32的GPIO学习笔记讲课教案

s t m32的G P I O学习 笔记

I/O口工作模式: 1.高阻输入 输入模式的结构比较简单,就是一个带有施密特触发输入(Schmitt-triggered input)的三态缓冲器(U1),并具有很高的阻抗。施密特触发输入的作用是能将缓慢变化的或者是畸变的输入脉冲信号整形成比较理想的矩形脉冲信号。 执行 GPIO管脚读操作时,在读脉冲(Read Pulse)的作用下会把管脚(Pin)的当前电平状态读到内部总线上(Internal Bus)。 2.推挽输出 推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高. 在推挽输出模式下,GPIO还具有回读功能,实现回读功能的是一个简单的三态门 U2。注意:执行回读功能时,读到的是管脚的输出锁存状态,而不是外部管脚 Pin的状态。 3.开漏输出 开漏是用来连接不同电平的器件,匹配电平用的,因为开漏引脚不连接外部的上拉电阻时,只能输出低电平,如果需要同时具备输出高电平的功能,则需要接上拉电阻,很好的一个优点是通过改变上拉电源的电压,便可以改变传输电平,比如加上上拉电阻就可以提供TTL/CMOS电平输出等。

开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管 T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到 GND(有一定内阻) 开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管 T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到 GND(有一定内阻). 4.钳位二级管 其作用是防止从外部管脚 Pin输入的电压过高或者过低。 提高输出电压一种简单的做法:是先在 GPIO管脚上串联一只二极管(如 1N4148),然后再接上拉电阻。 ///////////////////////////////////////////////////////////////////////////////////////////////////////// STM32的GPIO管脚深入分析: 概述:STM23的每个GPIO引脚都可以由软件配置成输出(推挽或开漏),输入(带或不带上拉或下拉)或复用的外设功能端口。多数GPIO引脚与数字或模拟的复用外设共用;除了具有模拟输入(ADC)功能的管脚之外,其他的GPIO引脚都有大电流通过能力。 tip:每个IO口可以自由编程,单IO口寄存器必须要按32位bit被访问。 STM32的每个IO端口都有7个寄存器来控制 一.具体如下8种模式:

用STM32一步一步点亮led灯

STM32之一步一步点亮led (2011-05-09 19:40) 标签: stm32led v3.4MDK 4.12入门分类:stm32 入手stm32以来,一直想快速上手,所以在各大论坛闲逛,各个达人的blog 上学习,正所谓欲速则不达,心急是吃不了热豆腐的!有木有? 最终决定使用st官网的库开发,据大侠们写道使用库可以快速上手,貌似的确如此,一个个教程写的那么好,直接拿过来用就是了。可是那么多个库,聪明的你请告诉到底选择哪一个啊?My God!实话实说,我被这些库折腾了个够!好吧,我最后还是承认最后用的是v3.4的库,是很方便! 切入正题,点亮LED。 硬件:红牛开发板,STM32F103ZET6(144封装). 软件:RealView MDK 4.12 stm32固件库:v3.4 附上自己整理后的库: V3.4_clean.rar 根据官网库自己整理了下,新建了工程模板如下图:(主要参考文章《在 Keil MDK+环境下使用STM32 V3.4库.pdf》)在KeilMDK+环境下使用STM32V3.4库.pdf 入图所示:新建一个目录01_ProLed,建议放在英文路径下,避免不必要的麻烦。将上面的库v3.4解压到此目录,再新建一个project目录,存放工程。 说明: CMSIS:最底层接口。StartUp:系统启动文件。StdPeriph_Lib:stm32外围设

备驱动文件。Project:工程文件。User:用户文件。新建工程步骤:此处略去300字。 简单说明: 1.core_cm3.c/core_cm3.h 该文件是内核访问层的源文件和头文件,查看其中的代码多半是使用汇编语言编写的。在线不甚了解。--摘自《在Keil MDK+环境下使用STM32 V3.4库》 2.stm32f10x.h 该文件是外设访问层的头文件,该文件是最重要的头文件之一。就像51里面的reg51.h一样。例如定义了 CPU是哪种容量的 CPU,中断向量等等。除了这些该头文件还定义了和外设寄存器相关的结构体,例如: 1.typedef struct

STM32各模块学习笔记

STM32 中断优先级和开关总中断 一,中断优先级: STM32(Cortex-M3) 中的优先级概念 STM32(Cortex-M3) 中有两个优先级的概念 —— 抢占式优先级和响应优先级,有人把响应优 先级称作 '亚优先级 '或 '副优先级 ',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应, 即中断嵌 套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当两个中断源的抢占式优先级相同时, 这两个中断将没有嵌套关系, 当一个中断到来后, 如 果正在处理另一个中断, 这个后到来的中断就要等到前一个中断处理完之后才能被处理。 如 果这两个中断同时到达, 则中断控制器根据他们的响应优先级高低来决定先处理哪一个; 如 果他们的抢占式优先级和响应优先级都相等, 则根据他们在中断表中的排位顺序决定先处理 哪一个。 既然每个中断源都需要被指定这两种优先级, 就需要有相应的寄存器位记录每个中断的优先 级;在 Cortex-M3 中定义了 8 个比特位用于设置中断源的优先级,这 8 个比特位可以有 8 种分配方式,如下: 这就是优先级分组的概念。 Cortex-M3 允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此 STM32 把指定中断优先级的寄存器位减少到 4 位,这 4个寄存器位的分组方式如下: 第 0 组:所有 4 位用于指定响应优先级 第 1 组:最高 1 位用于指定抢占式优先级,最低 第 2 组:最高 2 位用于指定抢占式优先级,最低 第 3 组:最高 3 位用于指定抢占式优先级,最低 第 4 组:所有 4 位用于指定抢占式优先级 所有 8 位用于指定响应优先级 最 高 1 位用于指定抢占式优先级, 最高 2 位用于指定抢占式优先级, 最高 3 位用于指定抢占式优先级, 最高 4 位用于指定抢占式优先级, 最高 5 位用于指定抢占式优先级, 最高 6 位用于指定抢占式优先级, 最高 7 位用于指定最低 7 位用于指定响应优先级 最低 6 位用于指定响应优先级 最低 5 位用于指定响应优先级 最低 4 位用于指定响应优先级 最低 3 位用于指定响应优先级 最低 2 位用于指定响应优先级 最低 1 位用于指定响应优先级 3 位用于指定响应优先 级 2 位用于指定响应优先 级

STM32入门基本知识

STM32学前班教程之一:选择他的理由 经过几天的学习,基本掌握了STM32的调试环境和一些基本知识。想拿出来与大家共享,笨教程本着最大限度简化删减STM32入门的过程的思想,会把我的整个入门前的工作推荐给大家。就算是给网上的众多教程、笔记的一种补充吧,所以叫学前班教程。其中涉及产品一律隐去来源和品牌,以防广告之嫌。全部汉字内容为个人笔记。所有相关参考资料也全部列出。:lol 教程会分几篇,因为太长啦。今天先来说说为什么是它——我选择STM32的原因。 我对未来的规划是以功能性为主的,在功能和面积之间做以平衡是我的首要选择,而把运算放在第二位,这根我的专业有关系。里面的运算其实并不复杂,在入门阶段想尽量减少所接触的东西。 不过说实话,对DSP的外设并和开发环境不满意,这是为什么STM32一出就转向的原因。下面是我自己做过的两块DSP28的全功能最小系统板,在做这两块板子的过程中发现要想尽力缩小DSP的面积实在不容易(目前只能达到50mm×45mm,这还是没有其他器件的情况下),尤其是双电源的供电方式和的电源让人很头疼。 后来因为一个项目,接触了LPC2148并做了一块板子,发现小型的ARM7在外设够用的情况下其实很不错,于是开始搜集相关芯片资料,也同时对小面积的AVR和51都进行了大致的比较,这个时候发现了CortexM3的STM32,比2148拥有更丰富和灵活的外设,性能几乎是2148两倍(按照MIPS值计算)。正好2148我还没上手,就直接转了这款STM32F103。 与2811相比较(核心供电情况下),135MHz×1MIPS。现在用STM32F103,72MHz×,性能是DSP的66%,STM32F103R型(64管脚)芯片面积只有2811的51%,STM32F103C型(48管脚)面积是2811的25%,最大功耗是DSP的20%,单片价格是DSP的30%。且有更多的串口,CAP和PWM,这是有用的。高端型号有SDIO,理论上比SPI速度快。 由以上比较,准备将未来的拥有操作系统的高端应用交给DSP的新型浮点型单片机28335,而将所有紧凑型小型、微型应用交给STM32。 STM32学前班教程:怎么开发 sw笨笨的STM32学前班教程之二:怎么开发目前手头的入门阶段使用的开发器概述 该产品为简易STM32调试器和DEMO板一体化的调试学习设备,价格在一百多块。 2、硬件配置

stm32pwm输入捕捉模式学习笔记

stm32 pwm输入捕捉模式学习笔记 (本文来自:android_chunhui的博客) PWM输入是输入捕获的一个特殊应用,输入捕获就是当连接到定时器的引脚上产生电平变化时对应的捕获装置会立即将当前计数值复制到另一个寄存器中。你可以开启捕获中断然后在中断处理函数中读出保存的计数值。主要用于读取pwm的频率和占空比。 与输入捕获不同的是PWM输入模式时,用到两个通道(一般用TIMx_CH1或TIMx_CH2),只给其中一个通道分配gpio时钟即可,另一个在内部使用。给一个通道分配gpio时钟后,需要设置另一个为从机且复位模式。(例如使用ch2,ch1就得设置成从机模式)。当一个输入信号(TI1或TI2)来临时,主通道捕获上升沿,从机捕获下降沿。 假设pwm从低电平开始触发,当上升沿来临时,两个通道TIM_CNT均复位开始计数,下一个下降沿来临,从机读取TIM_CNT中的值,记为CCR1,下一个上升沿来临,主通道读取TIM_CNT的值,记为CCR2。所以CCR2/f,为pwm周期,倒数即频率。CCR1/CCR2就是占空比。 下面是pwm捕获模式下的配置: void Tim2_PWMIC_Init(void) { TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //***通道选择,通道一为从机TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿触发 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //管脚与寄存器对应关系TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入预分频。意思是控制在多少个输入周期做一次捕获,如果 //输入的信号频率没有变,测得的周期也不会变。比如选择4分频,则每四个输入周期才做一次捕获,这样在输入信号变化不频繁的情况下, //可以减少软件被不断中断的次数。 TIM_ICInitStructure.TIM_ICFilter = 0x0; //滤波设置,经历几个周期跳变认定波形稳定0x0~0xF TIM_PWMIConfig(TIM2, &TIM_ICInitStructure); //根据参数配置TIM外设信息TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); //选择IC2为始终触发源 TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);//TIM从模式:触发信号的上升沿重新初始化计数器和触发寄存器的更新事件 TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //启动定时器的被动触发 TIM_Cmd(TIM2,ENABLE); //启动TIM2 TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); //打开中断 } //中断服务函数

STM32F103RCT6使用说明

STM32开发板使用手册 风帆 STM32开发板是风帆电子为初学者学习STM32 Cortex M3 系列ARM 而设计的学习板。以STM32F103RCT6芯片为核心,配套2.4/2.8寸彩色TFT屏模块,板载UART、USB、ADC电压调节、按键、JTAG接口、彩屏接口、流水灯、SD卡接口、IO引出口等多种硬件资源。

JTAG 口 2个LED 灯 GPIOA 引出1O USB 串口1 DS10B20预留 HS0038红外接收头 红外温度传感器连接头 GPIOB@C 引出IO OLED@LCD 共用接口 STM32F103RCT6 2.4/2.8寸LCD 接口 485芯片 RS485接口 1:A; 3:B NRF24L01 模块接口 W25Q1 6 FLASH 芯片 SD 卡接口(在背面) JF24C 模块预留接口 GPIO C@D 引出IO 蜂鸣器跳线 PS/2鼠标键盘接口 三个按 键: WAKEUP KEY0 KEY1 RESET 按键 Rs232接口 电源开关 USB 接口 电源指示灯 自恢复保险丝 MAX232 电源芯片 24c02 3.3V 、5V 电 源输出; 线序为: GND/3.3V GND/5V BOOT 设置 线序为: GND /GND BOOT1/BOOT0 3.3V/3.3V

此板子不管硬件还是软件完全无缝接兼容正点原子的MINSTM32,并对MINSTM32进行了完美的升级,让我们用最少的钱做更多的事,具体升级的部分包括: 1、C PU的升级 利用ST意法半导体的CPU兼容性强的优点,此板采用比 STM32F103RBT6性能更强、且完全兼容的的STM32F103RCT6升级 CPU,把完美的MINNI STM板子的功能发挥到极致,具体2个CPU 的主要资源对比如下: 可以看出,FLASH增加了一倍,达到256K,RAM也增加了1倍,让 我们不用再为FLASH\RAM小而烦恼,使我们的存储空间更为强大; 增加了一个16位普通IC/OC/PWM),2个16位基本(IC/OC/PWM),1个STI,2个USART,这里比STM32F103RB还多了一个DAC通 道,这个STM32F103RB是没有的

STM32学习笔记之二_中断

STM32中中断的理解 一、什么是中断 中断是指在计算机执行程序的过程中,当出现异常情况或者特殊请求时,计算机停止现行的程序的运行,转而对这些异常处理或者特殊请求的处理,处理结束后再返回到现行程序的中断处,继续执行原程序。 中断处理过程: (1)保护被中断进程现场。为了在中断处理结束后能够使进程准确地返回到中断点,系统必须保存当前处理机程序状态字PSW和程序计数器PC等的值。 (2)分析中断原因,转去执行相应的中断处理程序。在多个中断请求同时发生时,处理优先级最高的中断源发出的中断请求。 (3)恢复被中断进程的现场,CPU继续执行原来被中断的进程。 二、什么是中断服务程序 处理中断事件的程序被称为中断服务程序。 三、什么是中断向量 中断向量就是中断服务程序的入口地址。 四、什么是中断向量号 中断号也叫中断类型号,或者中断请求号。 中断是指在CPU运行期间,被CPU内部或外部事件所打断、暂停当前程序的执行而转去执行一段特定的处理内部或外部时间程序的过程。外部设备进行I/O操作时,会随机产生中断请求信号。这个信号中会有特定的标志,使计算机能够判断是哪个设备提出中断请求,这个信号就叫做中断号。 五、什么是中断向量地址 中断向量地址就是内存中存放中断服务程序入口地址的地址。 六、什么是中断向量表 CPU是根据中断向量号获取中断向量值,即对应中断服务程序的入口地址值。因此为了让CPU由中断向量号查找到对应的中断向量,就需要在内存中建立一张查询表,即中断向量表。 七、STM32中中断发生时系统找到对应中断服务执行的过程 (1)根据中断设发生备确定对应的中断向量号。

(3)执行中断服务程序。 以ALIENTEK Mini STM32开发板范例代码中的定时器中断实验为例来说明。 (1)根据中断设发生备确定对应的中断向量号。 在main.c中: TIM3_Int_Init(4999,7199); 在timer.c中: void TIM3_Int_Init(u16 arr,u16 psc) { . . . NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断号 . . . } 在stm32f10x.h中: typedef enum IRQn { . . . TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ . . . } 根据以上三个文件可以确定,定时器TIM3对应的中断向量号为TIM3_IRQn,而TIM3_IRQn = 29,所以,定时器TIM3对应的中断向量号为29。

STM32教程(1)

第一部分开发板介绍 1.1 STM32开发板简介 开发板配置: ●CPU主芯片是STM32F103VCT6,主频72MHz,256KB FLASH ,48KB RAM; ●3个按键,可实现中断或查询方式判断是否有键按下; ●4个发光二极管LED,可进行流水灯或花样显示; ●1个无源蜂鸣器,可用PWM驱动; ●1个电位器,可配合内部AD进行AD转换; ●1个RS232串行通信接口,可使开发板与PC机进行通信; ●1个基于SPI串行总线的触摸屏转换接口芯片,可进行触屏操作; ●1个基于IIC串行总线的EEPROM,可进行数据存储; ●1个基于CPU片内SDIO的TF卡接口,可进行数据读写; ●1个FSMC控制的2.83英寸TFT液晶屏,可进行图片文字显示; ●1个蓝牙模块,可使开发板与PC机进行通信; ●1个USBmin2.0接口为开发板供电; ●所有I/O口引出,可通过跳线自行配置和自制外围模块连接;

下面介绍一下STN32开发板的各个部分。 1、LED灯 STM32开发板有4个LED灯,它们在开发板上的标号分别为LED1、LED2、LED3、LED4。在调试代码的时候,使用LED来指示程序状态,是非常不错的辅助调试方法。 2、按键 STM32开发板有三个普通按键,它们在开发板上的标号分别为KEY1、KEY2、KEY3。可以用于人机交互的输入,三个按键通过跳线帽连接到STM32的开发板的IO口上。 3、电源指示灯 开发板上有一个蓝色电源指示灯,它在开发板上的标号为LED5(POWER)。用于指示电源状态。该开发板通过USB供电,在该电源开启的情况下,指示灯亮,否则不亮。通过这个LED灯判断开发板的上电情况。 4、蓝牙 开发板上有一个蓝牙模块,它在开发板上的标号为Bluetooth。用于开发板与电脑进行无线通讯。 5、SD卡接口 SD卡接口在开发板上的标号为TF_Card。SD卡是最常见的存储设备,是很多数码设备的存储媒介,比如数码相框、数码相机、MP5等。STM32开发板自带了SD卡接口,可用于SD卡试验,方便大家学习SD卡。 6、AT24C01 EEPROM EEPROM型号为A T24C01,用于掉电数据保存。因为STM32内部没有EEPROM,所以开发板外扩了24C01,用于存储重要的数据,也可以用来做IIC实验,及其他应用。 7、RS232接口 RS232在开发板上的标号为J2。用于与电脑进行通信,也可以用来做USART实验。 8、滑动变阻器 滑动变阻器在开发板上的标号为ADJ_RES。通过调节滑动变阻器来改变电压值,可以用来做AD转换的实验。 9、蜂鸣器 蜂鸣器在开发板上的标号为Buzzer。通过调节定时器产生的PWM波的占空比来改变蜂鸣器的声音,可以用来做PWM实验,及其他应用。 10、液晶屏 触摸屏在开发板上的标号为TFT。用来显示一些图片和汉字。可以用来学习触摸屏的一些实验。触摸屏都需要一个AD转换器,STM32开发板触摸屏控制芯片为TSC2046。 11、引出IO口 开发板有很多引出IO口,可以通过跳线帽选择是连接各部分的功能模块还是用作引出IO 口,引出的IO口方便大家使用,可以连接外部器件。 1.2 STM32开发板硬件详解 本节介绍STM32开发板的各部分硬件,让大家对开发板的各部分硬件原理有个了解。

详细的STM32单片机学习笔记

详细的STM32单片机学习笔记 STM32单片机学习笔记 1、AHB系统总线分为APB1(36MHz)和APB2(72MHz),其中21,意思是APB2接高速设备 2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h 专门控制外围器件的配置,也就是开关头文件的作用 3、HSE Osc(High Speed External Oscillator)高速外部晶振,一般为8MHz,HSI RC(High Speed InternalRC)高速内部RC,8MHz 4、LSE Osc(Low Speed External Oscillator)低速外部晶振,一般为32.768KHz,LSI RC (Low Speed InternalRC)低速内部晶振,大概为40KHz左右,提供看门狗时钟和自动唤醒单元时钟源 5、SYSCLK时钟源有三个来源:HSI RC、HSE OSC、PLL 6、MCO[2:0]可以提供4源不同的时钟同步信号,PA8 7、GPIO口貌似有两个反向串联的二极管用作钳位二极管。 8、总线矩阵采用轮换算法对系统总线和DMA进行仲裁 9、ICode总线,DCode总线、系统总线、DMA总线、总线矩阵、AHB/APB桥 10、在使用一个外设之前,必须设置寄存器RCC_AHBENR来打开该外设的时钟 11、数据字节以小端存储形式保存在存储器中 12、内存映射区分为8个大块,每个块为512MB 13、FLASH的一页为1K(小容量和中容量),大容量是2K。 14、系统存储区(SystemMemory)为ST公司出厂配置锁死,用户无法编辑,用于对FLASH 区域进行重新编程。所以我们烧写程序务必选择BOOT1 = 0,这样通过内嵌的自举程序对

芯达STM32入门系列教程之三《如何使用J-Flash调试》

STM32入门系列教程如何使用J-Flash调试 Revision0.01 (2010-04-12)

对初学者来说,要进行STM32的程序下载调试,一般有三种方法: (1)使用SEGGER J-Flash(J-Link)下载程序到闪存中运行; (2)使用串口ISP来下载HEX文件到CPU中运行; (3)J-Link+MDK组合,来在线调试程序(可下载、调试)。 本文档讲述如何在芯达STM32开发板上使用SEGGER J-Flash下载HEX文件。而其他两种方法,我们将在文档《如何使用MDK+J-Link调试》、以及《如何使用STM32-ISP下载调试》中详细说明。 先来解释SEGGER。实际上,大家更为熟悉的ARM仿真器J-Link,就是由SEGGER公司开发的。J-Link是SEGGER为支持仿真ARM内核芯片推出的JTAG 仿真器。 不管什么CPU的仿真器,都需要安装其相应的驱动后才能使用。J-Link也不例外,它的驱动软件可以去官方网站:https://www.360docs.net/doc/a56608537.html,下载最新版本。这里使用的驱动软件版本是V4.08l,该驱动的安装非常简单,请参考文档《如何安装J-Link驱动软件》。 安装完毕,会出现如下两个图标: 现在开始我们的工作吧! 步骤一先进行设备连接操作。芯达STM开发板的JTAG口(开发板面朝上,最顶端有一个JTAG20pin的插口),与J-Link V8仿真器的输出排线连接,J-Link另一头的USB插口则插在电脑的USB口上。这时,J-Link的指示灯开始闪烁,并保持“点亮”的状态。 注意:大家购买J-Link仿真器的时候,JTAG接口要求是标准的20pin的2.54间距的针座。否则需要转接卡进行JTAG接口的转换。 步骤二进入PC的桌面,点击上图左边的图标:J-Flash ARM V4.081,出现如下界面:

STM32学习心得笔记

STM32学习心得笔记 时钟篇 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍, 但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外, 实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB 模块,其串行接口引擎需要一个频率为48MHz的时

钟源。该时钟源只能 从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL 必须使能, 并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL 输出、HSI或者HSE。系统时钟最 大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分 频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB 总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz), 另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

(完整版)STM32F103通用教程

STM32F103_使用心得 IO端口输入输出模式设置:...........; Delay延时函数:..............; IO端口使用总结:...............; IO口时钟配置:................; 初始化IO口参数:...............; 注意:时钟使能之后操作IO口才有效!......; IO端口输出高低电平函数:...........; IO的输入 IO端口输入输出模式设置: (1) Delay延时函数: (2) IO端口使用总结: (2) IO口时钟配置: (2) 初始化IO口参数: (2) 注意:时钟使能之后操作IO口才有效! (2) IO端口输出高低电平函数: (2) IO的输入和输出宏定义方式: (3) 读取某个IO的电平函数: (3) IO口方向切换成双向 (3) IO 口外部中断的一般步骤: (3) 内部ADC使用总结: (4) LCDTFT函数使用大全 (5) TFTLCD使用注意点: (5)

IO端口宏定义和使用方法: (6) Keil使用心得: (6) ucGUI移植 (6) DDS AD9850测试程序: (6) ADC 使用小结: (7) ADC测试程序: (9) DAC—tlv5638测试程序 (9) 红外测试程序: (9) DMA使用心得: (9) 通用定时器使用: (9) BUG发现: (10) 编程总结: (10) 时钟总结: (10) 汉字显示(外部SD卡字库): (11) 字符、汉字显示(内部FLASH) (12) 图片显示: (16) 触摸屏: (17) 引脚连接: (19) IO端口输入输出模式设置: Delay延时函数: delay_ms(u16 nms); delay_us(u32 nus); IO端口使用总结: 1)使能IO 口时钟。调用函数为RCC_APB2PeriphClockCmd()。 2)初始化IO 参数。调用函数GPIO_Init();

相关文档
最新文档