从2018年十月到2019年六月断断续续学习STM32已经大半年了,期间也做过一些整理,写过一些通用代码,可都无疾而终,为了系统性地巩固所学,决定一博客的形式做一遍整理.
所用硬件是STM32 F103C8T6(是市面上常见且便宜的最小系统板),软件是KEIL5,按自己风格写了一份工程模板,里面还有之前未写完的通用代码(写代码一定要注重 可读性 可移植性 通用性,移植过放荡不羁的代码才深觉不写注释,难以移植的代码是毒瘤),之前所有的基础只有C++,没摸51直接入手32(看的原子与野火的教程,都详细且良心,个人更喜欢野火的风格),对寄存器了解不深刻,只能做库函数开发这个样子,但是既然已经入门就该有系统的总结,写博客给自己复习,给小白引路,如有错误欢迎斧正
靡不有初,鲜克有终 希望你能写完这系列博客
言归正传,单片机界的"Hello World!"应该非点LED莫属了,先抛开天花乱坠的术语们,先点亮一个LED得到板子的反馈才算入了嵌入式的门(总是先在实践中成长,后在理论中升华)
目录
[1]硬件条件
[2]软件条件
[3]控制代码
[4]编译下载运行
[5]有关GPIO
(1)最小系统板C8T6(某宝上十元左右)
(2)Jlink(土豪买正版,买盗版可能会有毒)
附上自己中的毒以及解决方法 https://blog.csdn.net/arthurhope/article/details/86624261
(3)LED(一般板子上会有贴片LED)
(1)安装KEIL5
(2)F103的工程模板
之前写的教程 https://blog.csdn.net/arthurhope/article/details/86673592 里面有我的模板
原子野火的资料包里都有各自风格的模板初学者可以先COPY着,入门之后学着自己建就好了
(1)在工程模板根目录下建立一个文件夹 在此文件夹下建立 led.c以及led.h两个文件,当然你可以把代码写主函数里
但是这样很不讲究,个人意见main.c越干净越好,例如:
记得有头文件的文件夹都要 Include Paths
(2)上代码
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
void LED_Configuration(void);
#define LED_OFF() GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define LED_ON() GPIO_ResetBits(GPIOB,GPIO_Pin_12)
#endif
#include "led.h"
/*********************************************************************************
*@brief LED配置
*@param none
*@retval none
*@note PB12 3V3
**********************************************************************************/
void LED_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//GPIO 初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;//引脚选择
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出速率选择
GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIO
GPIO_SetBits(GPIOB,GPIO_Pin_12);//默认拉高PB12电平
}
#include "initialization.h"
int main()
{
System_Init(); ///系统初始化
delay_ms(500); ///保证上一步完成
System_Config(); ///系统初始设置
delay_ms(500); ///保证上一步完成
SysTick_Config(72000); ///得到1ms的SysTick可用作主进程
while(1){;} ///主循环
}
/**************************************************************************************************
* @brief 系统心跳
* @param none
* @retval none
***************************************************************************************************/
void SysTick_Handler(void)
{
LED_OFF();
delay_ms(500);
LED_ON();
delay_ms(500);
}
(3)注解
void SysTick_Handler(void)中断中的内容可以搬到while(1){;} 主循环中,个人喜欢用中断
LED接PB12 与 VCC是查询最小系统版原理图得知的,外接LED的可以任用一个IO
(传不了视频GIF有点糊)
写完这些发现略显啰嗦下篇博客改进,有关问题欢迎在评论区提出
•基本功能 八种工作模式
上拉输入(GPIO_Mode_IPU) 输入口默认高电平
下拉输入(GPIO_Mode_IPD) 输入口默认低电平
浮空输入(GPIO_Mode_IN_FLOATING) 用于通讯协议(如USART)接收端
模拟输入(GPIO_Mode_AIN) 将电信号传送外设(如ADC)采集
推挽输出(GPIO_Mode_Out_PP) 普通3.3V输出
开漏输出(GPIO_Mode_Out_OD)用于非匹配电压输出需外接上拉电阻且有”与”特性
复用推挽(GPIO_Mode_Out_AF_PP)GPIO复用作为串口
复用开漏(GPIO_Mode_Out_AF_OD)用于IC SMBUS等需要线与功能的场合
•常用函数
初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx,GPIO_InitStruct);
读取电平函数
uint8_t GPIO_ReadIntputDataBit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
uint16_t GPIO+ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOuttputDataBit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
uint16_t GPIO+ReadOutputData(GPIO_TypeDef* GPIOx);
设置输出电平函数
void GPIO_SetBits(GPIO_Typedef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_Typedef* GPIOx, uint16_t GPIO_Pin);
•配置要点
(1)配置GPIO前先调用函数 RCC_ABP2PeriphClockCmd()函数使能相应时钟
(2)调用GPIO_Init() 并配置相关参数,初始化IO口
(3)根据所需功能选择GPIO工作模式,然后对GPIO进行操作