前几天实验室搬家的时候在垃圾堆里翻出了一块黑色的小板子
我一看,咦!有LED、有按键、有复位开关、还有晶振,虽然平常玩的都是四四方方的F1系列的芯片,这种长方形的芯片还是第一次见过,上面的英文也不是很能直观的分辨出来是什么型号的芯片。但是,凭证直觉告诉我,这玩意肯定是一块开发板,然后我就去淘宝问被我码掉店家名字的客服有没有这块开发板的资料,他态度非常之差的跟我回复说没有,这怎么可能嘛,自己家店铺生成出来的开发板,怎么可能会没有资料呢,所以我就给开发板店铺名字打码了。
秉着自己动手丰衣足食的思想,我把芯片上的全部英文都打上度娘的搜索框,终于还给我找到了,嘿嘿!这货是一块STM32F030F4P6的芯片。
这款单片机Flash很小,引脚也不多,但是串口、IIC、ADC资源该有的都还是有的,而且这款芯片价格低体积小应该是适合小型设备开发的。想着以后工作可能会用的上,所以撑着没事提前捣鼓一下,顺便写个博客记录下学习过程。
先随便创建一个文件夹,然后在文件里面创建六个子文件夹:USER(用来存放main.c文件和项目文件)、CORE(核心文件如启动文件啥的头文件)、STLIB(ST的一些官方库文件如GPIO、IIC啥的)、SYSTEM(该文件用来存放自定义的芯片资源,如串口、ADC)、HAREWARD(存放一些外部硬件初始化文件,如LED、按键)、OBJ(用来存放编译后的文件)。
现在进入第二步准备工作,把需要用到的基础系统文件移植到我们新创建的文件夹中。可以到ST的官网自己下载F0系列的工程移植包,当然贴心的博主肯定会为你们准备好的了。
点击此处下载即可 提取码:4dv2
然后第一步:先把ST的官方库复制到我们刚刚创建的STLIB文件夹里面。
可以看看里面具体东西,留着备用,其实就是前面介绍的ST官方的芯片资源库文件。
第二步:先到下面路径找到stm32f0xx.h文件和system_stm32f0xx.h,把两个文件复制到我们创建的CORE文件夹。
再到下面路径找到core_cm0.h文件复制到CORE文件夹
再到下面路径找到system_stm32f0xx.c文件复制到CORE文件夹
再到下面路径找到启动文件startup_stm32f030.s,这个文件也是很重要的一个文件,也复制到CORE文件夹。
最后一个了,到下面路径找到stm32f0xx_conf.h文件,同意复制到CORE文件里面。
让我们看看CORE文件夹下面的六个文件
先留着备用,现在进入第三步:先在SYSTEM文件夹下创建一个DELAY文件夹用来存放延时函数的文件,再到HAREWARD文件夹下面创建LED和KEY文件夹,用来存放LED和KEY的定义。
<------------------------------------------------------------------分割线--------------------------------------------------------------------------->
一切准备就绪,开始创建工程文件写代码。
打开Keil5,Project—>New uVision Project。新建工程保存到刚建立的USER文件夹,第一次建立工程会让你选择对应的芯片包,选择自己相应型号的芯片即可,点击ok。
可能有些朋友找不到这玩意,只有F1的或者F4的。因为F0系列Pack还没安装,下载一个安装就行了,安装流程就省略了,可自己百度。
F0系列Pack包下载 提取码:2hlr
看下我们新建项目的工程目录,给他管理一下。右击Target 1选择Manage Project。
把我们刚刚创建的几个文件夹再到工程项目里面创建一遍。
再右击CORE文件夹,选择如下选项:添加外部文件到CORE文件夹。选择startup_stm32f030.s和system_stm32f0xx.c文件,点击Add。
再用同样方法把STLIB文件夹—>src目录下的全部.c文件添加到工程目录STBLIB下。
再包含下头文件:USE_STDPERIPH_DRIVER,STM32F030,同样流程添加STLIB——>inc文件。
选择一下输出文件的路径。
点击F7编译下看下输出。
有一个错误,意思是缺少一个main函数,一切没有问题接下来开始编写功能性代码,现在USER目录下创建一个main.c文件。右击USER文件夹—>Add New Item to Group USER。
用同样的流程添加delay.c、delay.h、led.c、led.h、key.c、key.h到上面所建立的DELAY、LED和KEY三个文件夹,添加完成之后包含下头文件路径。
就下来就是写代码环节,先把延时函数写好,带下要用。延时函数都大同小异,直接复制就行了。
/**************delay.h**************/
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f0xx.h"
void Delay_Init(void);
void delay_ms(uint16_t nms);
void delay_us(uint16_t nus);
#endif
/**************delay.c**************/
#include "delay.h"
static uint8_t fac_us = 0;
static uint16_t fac_ms = 0;
/***********************************************************
SYSTICK的时钟固定为HCLK时钟的1/8,即48M/8=6MHz,每个周期为
1/6000 000s为1/6us,所以fac_us=48/8=6。fac_ms=fac_ms*1000
***********************************************************/
void Delay_Init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us = SystemCoreClock/8000000;
fac_ms = (uint16_t)fac_us * 1000;
}
void delay_ms(uint16_t nms)
{
uint32_t temp;
SysTick->LOAD = (uint32_t)nms * fac_ms; //装载计数值
SysTick->VAL = 0x00; //清空计数器
SysTick->CTRL = 0x01; //计数开始
do
{
temp = SysTick->CTRL;
}
while((temp & 0x01) && (!(temp & (1 << 16)))); //等待计时到达
SysTick->CTRL = 0x00; //关闭计数器
SysTick->VAL = 0x00; //清空计数器
}
void delay_us(uint16_t nus)
{
uint32_t temp;
SysTick->LOAD = (uint32_t)nus * fac_us; //装载计数值
SysTick->VAL = 0x00; //清空计数器
SysTick->CTRL = 0x01; //计数开始
do
{
temp = SysTick->CTRL;
}
while((temp & 0x01) && (!(temp & (1 << 16)))); //等待计时到达
SysTick->CTRL = 0x00; //关闭计数器
SysTick->VAL = 0x00; //清空计数器
}
接下来是LED初始化使能函数。我这里PA4是按照开发板上面的LED灯来的,可按自己实际需求修改。
/**************led.h**************/
#ifndef __LED_H
#define __LED_H
#include "stm32f0xx.h"
#define LED(flag) if(flag) GPIO_ResetBits(GPIOA, GPIO_Pin_4);\
else GPIO_SetBits(GPIOA, GPIO_Pin_4);
void LED_Init(void);
#endif
/**************led.c**************/
#include "led.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
}
按键初始化使能函数。
/**************key.h**************/
#ifndef __KEY_H
#define __KEY_H
#include "stm32f0xx.h"
void KEY_Init(void);
#endif
/**************key.c**************/
#include "key.h"
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
主函数
#include "delay.h"
#include "led.h"
int main(void)
{
unsigned char flag = 0;
Delay_Init();
LED_Init();
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0)
{
delay_ms(100);
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0)
{
flag = !flag;
}
}
LED(flag);
}
}
编译下载看下运行结果
LED默认状态为熄灭,按一下按键LED亮,再按一下熄灭。
大功告成