STM32使用心得

2020-03-03 20:50:50 来源:范文大全收藏下载本文

stm32使用心得

第一次使用stm32,以前用过

51、avr、pic、2812,感觉stm32还真有点不一样,呵呵。

因为是第一次使用,下面说的肯定有不少错误,诚心求大家指正。

这次做的是用stm32f103zd+lattice 的lc4256v做一个波形发生器。通过上位机可以控制生成波形的频率,然后stm32根据频率计算波形占空比数据,通过总线形式传给cpld,然后cpld把这些数据转换成相对应占空比的pwm输出,外部接RC滤波电路,产生相对应的波形。由于频率范围较大,计算量也比较大,所以采用了stm32+cpld的结构。Stm32运行在72MHZ,通过mco脚给cpld 36M HZ的时钟,stm32和cpld通过总线方式通信。

此系统中Stm32主要用到的资源是:一个UART,一个TIMER及其中断,FSMC和DMA。

本人总结了下,Stm32初始化一个片内外设一般过程一般有以下几部分:

1.InitStructure配置及初始化

2.时钟使能

3.相对应的IOInitStructure配置及初始化

4.相对应的IO时钟使能

5.外设使能

6.中断配置及中断程序编写

下面介绍一下自己所用的UART、TIMER、FSMC、DMA的初始化。

UART初始化:

此系统中使用的是UART2,未用UART中断。UART初始化主要有:IO初始化,UART InitSturcture初始化,UART时钟使能,UART使能。程序如下: GPIO_InitTypeDef GPIO_InitStructure;

// Configure USART2_Tx as alternate push-pull

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

// Configure USART2_Rx as input floating

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

//IO时钟使能

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

USART_InitTypeDef USART_InitStructure;

/* USART2 configured as follow:

- BaudRate = 9600 baud

- Word Length = 8 Bits

- One Stop Bit

- No parity

- Hardware flow control disabled (RTS and CTS signals)

- Receive and transmit enabled

*/

USART_InitStructure.USART_BaudRate = 9600;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No ;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

/* Configure the USART2*/

USART_Init(USART2, &USART_InitStructure);

//UART时钟使能

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

/* Enable the USART2 */

USART_Cmd(USART2, ENABLE);

TIMER初始化

使用的是TIM2。初始化主要包括TIM2 InitSturcture初始化,时钟使能,TIM2开启,中断配置,及中断服务程序编写。此TIM2作用主要是给DMA提供时钟,DMA在TIM2 UP时启动一次DMA发送过程。TIM2程序如下:

TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;

//定时器2

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseStructure.TIM_Period = 33;

TIM_TimeBaseStructure.TIM_Prescaler = 71;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_ClearFlag(TIM2,TIM_FLAG_Update);

TIM_ARRPreloadConfig(TIM2,ENABLE);

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

TIM_Cmd(TIM2, ENABLE);

//中断配置

/* Enable the TIM2 gloabal Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

//定时器2中断服务程序

void TIM2_IRQHandler(void)//这个函数可以在文件stm32f10x.c文件中查找到 {

TIM_ClearITPendingBit(TIM2,TIM_IT_Update);

}

FSMC初始化

FSMC主要用来和CPLD进行总线通信,由DMA方式发送,在TIM2计时时间到后启动一次DMA发送,发送的数据由已计算好的数组中的一个16位数据以16位方式发给FSMC的地址。由于此系统电路已固定,stm32与CPLD间数据线是8位,故在向FSMC地址写16位数据时,FSMC会将数据拆成2部分发送。本人在实际编程时发现,如向*(volatile u16*)(Bank1_NOR4_ADDR+0x40)地址给CPLD写16位数据时,会在40h接收到低8位数据,在41h接收到高8位数据。按道理来说这些数据应该与NBL0, NBL1信号有关,本人在CPLD编程时未理会这个,具体时序不是很清楚,有待考究。

FSMC初始化程序如下:

FSMC_NORSRAMInitTypeDefFSMC_NORSRAMInitStructure;

FSMC_NORSRAMTimingInitTypeDefp;

p.FSMC_AddreSetupTime = 3;//6

p.FSMC_AddreHoldTime = 0;//3

p.FSMC_DataSetupTime = 8;//25

p.FSMC_BusTurnAroundDuration = 0;

p.FSMC_CLKDivision = 0;

p.FSMC_DataLatency = 0;

p.FSMC_AcceMode = FSMC_AcceMode_A;

FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;FSMC_NORSRAMInitStructure.FSMC_DataAddreMux = FSMC_DataAddreMux_Disable;

FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;

FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;

FSMC_NORSRAMInitStructure.FSMC_BurstAcceMode = FSMC_BurstAcceMode_Disable;

FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;

FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;

FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;

FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;

FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;

FSMC_NORSRAMInitStructure.FSMC_AsyncWait = FSMC_AsyncWait_Disable;

FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;

FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;

FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);

//IO初始化

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOG | RCC_APB2Periph_GPIOE |

RCC_APB2Periph_GPIOF, ENABLE);

/*-- GPIO Configuration -----------------------*/

/* SRAM Data lines configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 |

GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |

GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |

GPIO_Pin_15;

GPIO_Init(GPIOE, &GPIO_InitStructure);

/* SRAM Addre lines configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |

GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;

GPIO_Init(GPIOF, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |

GPIO_Pin_4 | GPIO_Pin_5;

GPIO_Init(GPIOG, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;GPIO_Init(GPIOD, &GPIO_InitStructure);

/* NOE and NWE configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5;

GPIO_Init(GPIOD, &GPIO_InitStructure);

/* NE4 configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_Init(GPIOG, &GPIO_InitStructure);

/* NBL0, NBL1 configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_Init(GPIOE, &GPIO_InitStructure);

此处简单介绍一下FSMC总线方式的使用。

FSMC初始化完了之后,进行如下定义,

#define Bank1_NOR4_ADDR((u32)0x6c000000)

#define cs_sin*(volatile u16*)(Bank1_NOR4_ADDR+0x40)

然后cs_sin=1000就是往这个地址写数字1000=0x03e8,则cpld 40h地址收到数据为0xe8,41h收到的数据为0x03

i=cs_sin,就是读这个地址的数据,由于定义的是16位的数据地址,故读到的数据是40h为低8位数据,41h为高8位数据

DMA初始化:

DMA在TIM2 UP时触发,将已经计算好放在数组dat_tocpld的16位数据发送到fsmc地址为(Bank1_NOR4_ADDR+0x40)的空间。

初始化程序如下:

DMA_InitTypeDef DMA_InitStructure;

DMA_DeInit(DMA1_Channel2);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* Enable TIM2 DMA interface */

TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(Bank1_NOR4_ADDR+0x

40);

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dat_tocpld;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 1152;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel2, &DMA_InitStructure);

/* Enable DMA1 Channel2 */

DMA_Cmd(DMA1_Channel2, ENABLE);

最后附上源自http://sxqstudy.blog.163.com/blog/static/34562512009625103148709/介绍的关于PWM电压转换电路。

在PWM用于DA转换的场合,阻容滤波电路是关系转换效果的重要环节。

由RC充放电常数我们可以大致计算出阻容环节的充放电频率,一般为了得到理想的滤波效果,这个频率要远小于PWM的输出频率(小于四分之一)。

一般情况下,当C较小R较大时,DA转换出的电压损耗很小,但是纹波却很大;当C较大R较小时,DA转换出的电压损耗很大,但纹波相对较小。

所以当需要进行线形度很高的精确DA转换时必须使用较小的滤波电容,且尽量避免使用电解类电容。而为了得到较强的信号输出,RC惯性环节之后还必须加一级高性能的电压跟随,然后在跟随器输出的地方加上一个滤波用的电解电容,用于平滑RC惯性环节的纹波。但是这还不够,因为这时的输出电压里可能含有较多的交流谐波成分,如果处理不当,跟随器有可能自激。解决的办法就是使用一个小的去藕电容。而且这里电容的放置顺序必须是电解电容在前,去藕电容在后!

如果输出电压精度和线形度要求不高,但是对纹波要求却很高,或者这个电压比较固定时,可以使用电容较大的滤波组合。因为,虽然大电容的直流损耗较大,但是我们可以通过调节PWM占空比来达到要求的输出电压,或者通过一级AD转换的反馈来实现精确的固定电压输出。只是这里仍然要加一级电压跟随器,以便于后级采集电路使用,且AD采集点放置在跟随器输出处。

STM32机器人

STM32学习心得笔记

stm32学习经历

stm32定时器的区别

STM32 IAP在线升级

STM32 PWM输出总结

一体机使用心得

电子白板使用心得

电子白板使用心得

origin7.5使用心得

《STM32使用心得.doc》
STM32使用心得
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档
下载全文