您的位置:首页 > 其它

[ M3 PN ] STM32F10XXX(Cortex-M3) MDK-RAM 点亮流水灯

2014-03-02 21:10 751 查看

1 建立工程

根据MDK-RAM建立工程的步骤建立STM32F10_LED新工程。

2 时钟

(1) 时钟信号

时钟信号 (Clock):时钟信号是提供给同步内存做讯号同步之用,同步记忆体的存取动作必需与时钟信号同步(只有时钟信号到来且存储命令同时到来时 才会发生存取动作)。同步是时钟控制系统中的主要制约条件,同步是指在有效信号沿发生时刻,希望写入单元的数据也有效。数据有效则是指数据量比较稳定(不发生改变),并且只有当输入发生变化时数值才会发生变化。由于组合电路无法实现反馈,所以只要输入量不发生变化,输出最后最终会是一个稳定有效的量。

将时钟信号总结为:同步记忆体只有在时钟信号和存取操作同时到来才会发生存取动作,而且一旦操作发生后会稳定保持存取操作过后的状态。直到新的时钟信号和新的操作来改变上一次得到的稳定状态。

(2) STM32系统时钟

系统时钟SYSCLK是供STM32中绝大部分部件工作的时钟源。SYSCLK可由PLL、HSI或者HSE提供输出,并且它通过AHB分频器分频后送给各模块使用。其中AHB分频器输出的时钟送给5大模块使用:

送给AHB总线、内核、内存和DMA使用的HCLK时钟。
分频后送给STM32芯片的系统定时器时钟。
直接送给Cortex的自由运行时钟FCLK。
送给APB1分频器。经APB1分频器后的一路输出供APB1外设使用(PCLK1),另一路送给”定时器(Timer)x”倍频器使用。该倍频器选择倍频后的时钟输出供”定时器x”使用。
送给APB2分频器。经APB2分频器后的输出一路供APB2外设使用(PCLK2),另一路送给“定时器y”倍频器使用。该倍频器选择倍频后的时钟输出供“定时器y”使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。[x和y的值具体看参考手册]。

Hclk为优秀的高性能总线(AHB bus peripherals)供给时钟信号(AHB为advanced high-performance bus)。Fclk(free running clock)为供给CPU内核的时钟信号,我们所说的cpu主频为XXXXMHz,就是指的这个时钟信号,相应的,1/Fclk即为cpu时钟周期。Pclk为优秀的高性能外设总线(APBbus
peripherals)供给时钟信号(其中APB为advanced peripherals bus)。

在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设(如GPIO)时钟等等。当需要使用某模块时,记得一定要先使能对应的时钟。而每个模块对应的时钟源自系统时钟,系统时钟源自时钟源(PLL, HSI, HSE等),所以在使能每个模块的时钟之前其实还需要配置系统时钟,即时钟初始化。

3 编写流水灯程序

编写一个流水灯程序的流程为:

根据原理图确定流水灯模块与STM32F10XXX芯片的连接关系。
根据STM32F10XXX参考手册查看需要配置得相关寄存器。
因为流水灯操作的是GPIO,所以需要使能GPIO模块的时钟。

因为GPIO模块的时钟源自APB2分频器分频后的PCLK2,AHB2分频器的时钟源自AHB分频器分频后的时钟信号,AHB分频器的时钟信号源于系统时钟,系统时钟源自几大时钟源。这就需要初始化时钟。

(1) 时钟初始化

时钟初始化是指配置“系统时钟SYSCLK频率”、“HCLK,PCLK时钟的分频值”。

如果工程中只添加了“启动文件”,添加到工程中的“启动文件”会调用”SystemInit()”及”main()”两个函数。那么我们就需要自己编码实现一个“系统文件”中”SystemInit()”功能的函数,且函数名需要为”SystemInit()”(不修改启动文件的话)。”SystemInit()”函数完成一些系统初始化的操作,其中就包含“时钟的初始化”,它被编写在“系统文件” ” system_stm32f10x.c“中。如果用户要自定义实现,按照功能根据参考手册配置时钟相关寄存器即可实现这些功能。

如果工程中连“启动文件”都没有添加,那么我们就需要自己编码实现“启动文件”和“系统文件”的功能。

如果在工程中添加了“启动文件”和“系统文件”,那么我们只要使能各模块时钟后就可以使用对应的时钟了。

在理清这个路线下的情况下,入门时可在工程中添加“启动文件”和“系统文件”,见MDK-RAM建立工程的步骤。然后直接通过使能的方式使用各模块的时钟。如Cortex-M3的板子的启动文件为”startup_stm32f10x.hds”,在建工程的过程中会提示用户添加,系统文件为”
system_stm32f10x.c”,包含” SystemInit()”函数,在固件库下的CMSIS中可以找到。

(2) 使能GPIO端口时钟

STM32中在使用任何一个外设都必须打开相应的时钟。经“时钟初始化”后,就可以直接使能GPIO时钟了,GPIO属APB2外设使用的是PCLK2( 查看《参考手册》 )。从原理图中看出流水灯模块连接到主控芯片的PORTE之上,见下图:



Figure1:Led与STM32芯片的连接关系

从原理图中可以看出来,led与PORTE的PORTE[0…2]引脚连接。故而需要打开PORTE的时钟。

(3) 配置GPIO寄存器设置引脚模式

明确PORTE[0…2]引脚的功能为”输出”。到”STM32F10XXX”参考手册中查看需要操作的寄存器为GPIOE_ CRL,GPIO_BSRR或GPIO_ODR。根据原理图可以看出,当PORTE[0..2]被置低时灯亮。以PORTE[0…2]引脚为对象,根据寄存器的配置需求将“GPIO时钟使能”和“引脚配置的功能”集成在一个函数内:

//LED Init

void LedInit(void)

{

//使能PORTE时钟

RCC->APB2ENR = 1 << 6;

//PORTE0~7清0

/设置PORTE[0…2]为输出、最大为10MHZ、通用推免模式

//PORTE[0..7]清0后将PORTE[0…2]拉高,不让灯亮

GPIOE->CRL &= 0x00000000;

GPIOE->CRL |= 0x000001 | 0x00000010 | 0x00000100;

GPIOE->BSRR &= 0x00000000;// GPIOE->ODR &= 0x00000000;

GPIOE->BSRR |= 1 | (1 << 1) | (1 <<2);//GPIOE->ODR |= 1 | (1 << 1)| (1 << 2);

}
其中在对PORTE[0..2]引脚置高低电平时通过GPIO_BSRR或者GPIO_ODR寄存器皆可。

(4) 灯闪烁

根据原理图中的电路关系,只要拉低PORTE[0..2]时led就会亮,拉高PORTE[0..2]时led就会灭,而给PORTE[0..2]置高低电平靠配置寄存器来实现。所以,要使led闪烁只需要用逻辑操作对应寄存器即可:

//LED blink

void LedBlink(void)

{

//PORTE[0..2]拉低,led[1..3]亮

GPIOE->BSRR |= (1 << 16) | (1 << 17) | (1<< 18); //GPIOE->ODR &= 0 | (0 << 1) | (0 << 2);

Delay(0x3FFFFF);



////PORTE[0..2]灭

GPIOE->BSRR |= 1 | (1 << 1) | (1 << 2); //GPIOE->ODR |= 1 | (1 << 1) | (1 << 2);

Delay(0x3FFFFF);

}
使Led亮和灭的语句可以被替换为注释的语句,其中Delay()延迟函数为:

//Delay

void Delay(__IO uint32_t nCount)

{

while(nCount--)

{

}

}

(5) 主程序

main()内容如下:

#include <stm32f10x.h>

#include <stdio.h>



//函数声明

void Delay(__IO uint32_t nCount);

void LedBlink(void);

void LedInit(void);



int main(void)

{

LedInit();

while(1){

LedBlink();

}

}
<stm32f10x.h>为stm32f10xxx系列芯片的头文件,其中定义了时钟、寄存器指针等类型。

(6) 调试运行

如果编译不通过就根据C语言知识和<stm32f10x.h>所规定的数据类型将程序调试正确。如果需要在线调试,就根据MDK-RAM-KEIL J-Link 在线调试进行调试。在keil中LOAD操作,如果没有在Debug中设置下载后就运行程序,则需要将板子重启后程序才会运行程序。

以上程序在吕师兄以STM32F103VC为微控芯片之上的板子的运行结果如下:



Figure2:闪烁的led灯

Practical Note Over.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: