建好工程,下一步,就是写程序了。就像所有的所有的上位机编程开始都会叫大家做个“hello world!”的程序一样,单片机编程的第一步呢,就是点亮LED灯。估计是因为这样能很直观地看到编程的效果吧,这样的教程经久不衰,哈哈。
接着上次的工程。忘了说一点,库版本是2.0.3,现在比较新的3.5.0,其中有一些不同之处,请注意。新建的文件夹中的startup和interrupt需要的文件比较固定,就不说了。lib下的文件和用户程序的关系比较密切,用户程序要调用一些库函数,这些库函数就必须放在工程中。以下,以点亮LED灯为例说明,IO口为PF的6和8。程序几乎是照抄的,我也是初学啊······
#include<stm32f10x_lib.h>
int main(void)
{
while(1)
{
GPIO_SetBits(GPIOF,GPIO_Pin_6);
GPIO_SetBits(GPIOF,GPIO_Pin_8);
GPIO_ResetBits(GPIOF,GPIO_Pin_6);
GPIO_ResetBits(GPIOF,GPIO_Pin_8);
}
}
这个大家应该都能看的差不多吧。第一行是头文件,相当于hello world!中的 #include <stdio.h>,至于详细作用,以后再说,今天的重点不在这里。while中的4行,是将6、8置位和复位,也就是输出高低电平,因为我还想让LED闪一闪。
这里就有问题了,置位和复位不该是写1和0吗?怎么是这样?
答案是:库函数。在工程部分的lib下,我们看到了四个.c文件,这是在建工程的时候加的,刚说过,这个和用户程序关系密切,希望自己好好想想,所以就不说怎么加了。(我知道是因为我的程序是照抄的!但是以后自己写的话,那指定没的抄!!!所以,要一开始就这样思考。)继续说程序,stm32f10x_gpio.c中有这两个函数的定义,大家可以去看下。推荐一下,source insight,很好用的。
因为要让LED闪,所以需要个延迟函数,这个大家都知道吧,爱放哪放哪吧,不说了。
又有个问题,怎么算延时时间呢?对了,时钟!不过,stm32的没单片机那么简单:这是个大问题。我们用一个函数来解决时钟问题,就用RCC_Cofigruation();吧,其中,在加点注释。
void RCC_Cofigruation(void)
{
ErrorStatus HSEStartUpStatus; //定义枚举类型的变量,为了下一步判断;
RCC_DeInit(); //复位系统时钟设置;
RCC_HSEConfig(RCC_HSE_ON); //开启HSE;
HSEStartUpStatus =RCC_WaitForHSEStartUp();//等待HSE起振;
if(HSEStartUpStatus == SUCCESS) //是否HSE起振;
{
RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK为SYSCLK1分频;
RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2为HCLK1分频;
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1为HCLK2分频;
FLASH_SetLatency(FLASH_Latency_2); //Flash延时周期为2;
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能Flash预取缓存;
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);//PLL设置;
RCC_PLLCmd(ENABLE); //PLL使能;
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET); //等待PLL稳定;
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选择PLL为SYSCLK;
while(RCC_GetSYSCLKSource()!=0x08); //等待PLL成为SYSCLK;
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); //开启GPIOF时钟;
}
以上就是时钟配置的全部程序。由于芯片内部有几条总线,所以要配置相应的时钟。同时,Flash要有个延时,IO口也要有自己时钟,这点是stm32的特殊地方。以前没见过,现在,知道了吧。这里面的函数,都在stm32f10x_rcc.c中,所以lib文件夹中要包括这个.c文件。对了,还要加上stm32f10x_flash.c,刚才用到了。
完了吗?没呢。还要设置IO口,就像以前用的单片机,总得确定是输入还是输出吧?不过,stm32要复杂不少,下面,还是一个函数:GPIO_Configuration();
voidGPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_8; //使用6和8;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; //最大翻转频率50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP; //推挽输出;
GPIO_Init(GPIOF,&GPIO_InitStructure); //使用PF;
}
结构体,熟悉吧?所有的IO口在使用时都需要设置,希望这是个好的模板。同样,这个structure的定义在stm32f10x_gpio.c中,记得加上。
里面的很多东西需要先看下stm32的基本情况才能理解,大家还是先去看下。到这里,程序就差不多了,把后面的两函数在主函数中调用下,前面声明,好习惯。下面,是完整的前半部分,后面的,已经很清楚了。
#include<stm32f10x_lib.h>
#define Delay(n)while((n--))
voidRCC_Cofigruation(void);
voidGPIO_Configuration(void);
int main(void)
{
vu32 n;
RCC_Cofigruation();
GPIO_Configuration();
while(1)
{
n=2000000;
GPIO_SetBits(GPIOF,GPIO_Pin_6);
GPIO_SetBits(GPIOF,GPIO_Pin_8);
Delay(n);
n=2000000;
GPIO_ResetBits(GPIOF,GPIO_Pin_6);
GPIO_ResetBits(GPIOF,GPIO_Pin_8);
Delay(n);
}
}
完成了,编译一下,没有错误,下载,运行,OK!LED灯在闪了!!!