一.工程文件模板
(7月15日)
我把过程分为三个步骤
1. 步骤一
新建文件夹
打开keil,new project,选择上面的文件夹,并建立工程名和选择芯片
2. 步骤二
建立start,library,user三个文件夹
将驱动(.s文件由汇编语言完成),内核寄存器,时钟的描述,stm32头文件放进start文件夹中
将库函数放到library文件夹中
将template中的main,conf(描述头文件之间的包含关系),it(中断函数描述和定义)放到user中
3. 步骤三
在三个方块的按钮里面新建三个文件
在start文件夹中添加文件
在library中添加文件
在user中添加文件
宏定义(由stm32f10x头文件的定义可知,要用stm32f10x_conf.h,就要宏定义)
添加路径(让keil找到这些文件)
debug(st_link) settings中打开reset and run;同时注意第二个febug中的sw。
打开main函数,删除原文件内容,并添加新内容(如下图所示)
最后一行必须是空行
二.GPIO
1.简介
GPIO(General Purpose Input Output)通用输入输出口
可配置为8种输入输出模式
引脚电平:0V~3.3V,部分引脚可容忍5V
输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
2.GPIO模式
通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式
- 浮空/上拉/下拉输入
- 模拟输入(接ADC模块)
- 开漏/推挽输出
- 复用开漏/推挽输出
`` 输出时,是可以输入的;而输入时,是不可以输出的。
3.常用函数
- RCC初始化GPIO时钟
示例
- GPIO相关函数
高低电平设置
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //0
GPIO_SetBits(GPIOA,GPIO_Pin_0); //1
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET); //0
GPIO_WriteBit(GOIOA,GPIO_Pin_0,Bit_SET); //1
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0; //0
GPIO_WriteBit(GOIOA,GPIO_Pin_0,(BitAction)1); //1
//可以用写1或0来设置电平,需要将将数字强制转换成枚举类型BitAction,Bit_RESET和Bit_SET也是枚举类型BitAction
参考
//复位函数,调用这个函数后,所指定的GPIO外设就会被复位
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
//复位函数,可以复位AFIO外设
void GPIO_AFIODeInit(void);
//初始化函数,功能:用结构体的参数来初始化GPIO口
//初始化时,我们需要先定义一个结构体变量,然后给结构体赋值,最后调用初始化函数,函数内部会自动读取结构体的值,然后把外设的各个参数配置好。
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
//功能:把结构体变量赋一个默认值
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
//以下四个函数为GPIO的读取函数,均有返回值
//功能:读取输入数据寄存器某一个端口的输入值
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:读取整个输入数据寄存器
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
//功能:读取输出数据寄存器的某一位,用于输出模式下,查看输入的值
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:读取整个输出数据寄存器
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
//以下四个函数为GPIO的写入函数
//功能:将指定端口引脚设置为高电平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:将指定端口引脚设置为低电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:对指定端口进行写入操作
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
//功能:同时对16个端口进行写入操作
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
/*参数注释:
*①GPIO_TypeDef* GPIOx,GPIO端口选择,值为GPIOx(x=A~G);
*可用按位或(|)来选择多个端口
*
*②uint16_t GPIO_Pin,IO口引脚选择,一个GPIO端口有16个引脚,所以其值为GPIO_Pin_x(x=0~15)
*可用按位或(|)来选择多个引脚
*
*③BitAction BitVal,指定写入的数据值,这个参数可以是BitAction枚举中的一个值,值为:
* @arg Bit_RESET:清除端口值,即置低电平
* @arg Bit_SET:设置端口值,即置高电平
*
*④uint16_t PortVal,指定要写入端口输出数据寄存器的值
*
*⑤GPIO_InitTypeDef* GPIO_InitStruct,GPIO初始化结构体的地址
*/
/*初始化结构体定义:
*①定义一个结构体变量
*GPIO_InitTypeDef GPIO_InitStructure;
*结构体如下:
*typedef struct
*{
* uint16_t GPIO_Pin;
* GPIOSpeed_TypeDef GPIO_Speed;
* GPIOMode_TypeDef GPIO_Mode;
*}GPIO_InitTypeDef;
*由此可知该结构体有三个成员,分别为GPIO_Pin、GPIO_Speed和GPIO_Mode,下一步就是分别赋值
*
*②给结构体赋值:
*GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置推挽输出
*GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //使用GPIO的0号引脚
*GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度为50MHz
*
*GPIO_Mode,用于设置工作模式,其枚举如下:
*typedef enum
*{ GPIO_Mode_AIN = 0x0, //模拟输入模式(Analog IN)
* GPIO_Mode_IN_FLOATING = 0x04, //浮空输入模式
* GPIO_Mode_IPD = 0x28, //下拉输入模式(In Pull Down)
* GPIO_Mode_IPU = 0x48, //上拉输入模式(In Pull Up)
* GPIO_Mode_Out_OD = 0x14, //开漏输出模式(Out Open Drain)
* GPIO_Mode_Out_PP = 0x10, //推挽输出模式(Out Push Pull)
* GPIO_Mode_AF_OD = 0x1C, //复用开漏模式(Atl Open Drain)
* GPIO_Mode_AF_PP = 0x18 //复用推挽模式(Atl Push Pull)
*}GPIOMode_TypeDef;
*
*GPIO_Pin,选择引脚,值为GPIO_Pin_x(x=0~15和All)
*
*GPIO_Speed,选择输出速度,其枚举如下:
*typedef enum
*{
* GPIO_Speed_10MHz = 1,
* GPIO_Speed_2MHz,
* GPIO_Speed_50MHz
*}GPIOSpeed_TypeDef;
*常用速度为50MHz
*/
4.实例
LED流水灯
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟
GPIO_InitTypeDef Init_GPIOStructure;
Init_GPIOStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
Init_GPIOStructure.GPIO_Pin= GPIO_Pin_All; //使用GPIOA所有引脚
Init_GPIOStructure.GPIO_Speed=GPIO_Speed_50MHz; //速度为50HZ
GPIO_Init(GPIOA,&Init_GPIOStructure);//用结构体初始化GPIO,并控制GPIOA
while(1)
{
for(int i=0;i<8;i++)
{
GPIO_Write(GPIOA,~(0x0001<<i)); //按位移动
Delay_ms(500);
}
}
}
光敏电阻控制蜂鸣器
buzzer
#include "stm32f10x.h" // Device header
void Init_Buzzer(void) //蜂鸣器初始化
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
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_SetBits(GPIOB,GPIO_Pin_12);
}
void Buzzer_On(void) //打开蜂鸣器
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}
void Buzzer_Off(void) //关闭蜂鸣器
{
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
void Buzzer_turn(void) //蜂鸣器翻转(响变为不响或者不响变为响)
{
if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12)==0)
{
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
else
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}
}
lightsensor
#include "stm32f10x.h" // Device header
void Init_Lightsensor(void) //光敏电阻初始化
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
uint8_t sensor_get(void) //读出光敏电阻的输入(亮为低电平,暗为高电平)
{
return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
}
main
#include "stm32f10x.h" // Device header
#include "Buzzer.h"
#include "lightsensor.h"
int main(void)
{
Init_Buzzer(); //蜂鸣器初始化
Init_Lightsensor(); //光敏电阻传感器初始化
while(1)
{
if(sensor_get()==1) //(高电平时,蜂鸣器响;否则蜂鸣器不响)
{
Buzzer_On();
}
else
{
Buzzer_Off();
}
}
}
三、其他基础知识
- A15、B3、B4三个端口默认是JTAG调试端口,如果要作为普通端口,需要进行相关配置。
- 有源蜂鸣器:内部自带振荡器,频率固定
无源蜂鸣器:不带振荡器,要提供震荡脉冲才能发声,可以发出不同频率的声音