STM32标准库:IO接口的操作
GPIO
控制单个GPIO管脚
GPIO_WriteBit(GPIOx,GPIO_Pin,Bitval);
//GPIOx用于选择GPIO外设,可以是GPIOA,GPIOB...
//GPIO_Pin为对应的GPIO管脚,可以形如GPIO_Pin_x(x可以是0-15)
//Bitval为待写入的值,为BIT_SET(相当于1),BIT_RESET(相当于0),为了方便可以直接用(BitAction)(1)或者(BitAction)(0)
控制整个GPIO外设
GPIO_Write(GPIOx,PortVal);
//向整组GPIO外设写入数据,一次性对16个管脚进行写入
//PortVal例:0x0003(16位!)即0000 0000 0000 0000 0000 0000 0011,代表GPIO_Pin_0和GPIO_Pin_1为1,其他为0
读取单个GPIO管脚输入值
GPIO_ReadInputDataBit(GPIOx,GPIO_Pin);//返回单个GPIO管脚的值
读取整个GPIO外设输入值
GPIO_ReadInputData(GPIOx); //返回整个GPIO外设16个管脚的值
注:把Input换成Output,能够读取GPIO的输出值
初始化GPIO端口:
步骤:使能GPIO时钟,初始化IO,操控IO
GPIO_InitTypeDef GPIO_InitStructure;//创建结构体,包含了配置信息
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx | RCC_APB2Periph_GPIOx,ENABLE);//使能APB2外设时钟,启动APB2总线上的GPIOx外设的时钟,如果不在总线上启动,之后的操作就不会生效
//对于GPIO外设,参数1:RCC_APB2Periph_GPIOx(x可以是A,B...多个可以用用|分隔),参数2:ENABLE/DISABLE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x | GPIO_Pin_x;//选择GPIO管脚(x可以是0-15)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置IO接口速度(可选2/10/50MHz),只有在设置IO输出时起效
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//选择工作方式
/*工作模式
GPIO_Mode_AIN 模拟输入 GPIO_Mode_IN_FLOATING 浮空输入 GPIO_Mode_IPD 下拉输入
GPIO_Mode_IPU 上拉输入 GPIO_Mode_Out_PP 推挽输出 GPIO_Mode_Out_OD 开漏输出
GPIO_Mode_AF_PP 复用推挽 GPIO_Mode_AF_OD复用开漏 */
GPIO_Init(GPIOx,&GPIO_InitStructure); //根据GPIO_InitStructure中的参数初始化GPIOx的寄存器,参数1可以是GPIOA...
按键的硬件消抖需要使用电容,硬件成本上升,按键软件消抖伪代码如下:
if(!GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)){
delay_ms(20) //定时器延时20毫秒消抖
if(!GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)){
//按下后的执行代码
}
while(!GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)); //等待按键松开
}
FLASH
Flash的写入:
步骤:解锁,清除标志位,擦除,写入,清除标志位,锁
void FLASH_W(u32 add,u16 dat){ //Flash写入函数,add为32位Flash地址,dat为16位数据
FLASH_Unlock(); //解锁Flash读写操作
FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位
//FLASH_FLAG_BSY:忙标志位 FLASH_FLAG_EOP:操作结束标志位
//FLASH_FLAG_PGERR:编写错误标志位 FLASH_FLAG_WRPRTERR:页面写保护错误标志位
FLASH_ErasePage(add); //擦除指定的地址页,1页有4个字节
FLASH_ProgramHalfWord(add,dat); //从指定地址写入半个字 STM32中 1字 = 4字节 = 32位
FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位
FLASH_Lock();//锁定Flash读写操作
}
注:如果想要写入一个字,则dat需要定义为u32类型,写入函数改为FLASH_ProgramWord(add,dat);,其他大小参考固件库函数手册
Flash的读取:标准库中没有相关函数,所以自己写
u16 a; u32 add; //16位数据(半字) 32位地址
a = *(u16*)(add) //将地址强制转换为u16指针,然后读取该指针指向地址的值,返回半字的数据
//如果把a设置为u8,然后(u16*)改为(u8*),即可读取一个字节
蜂鸣器:
蜂鸣器:蜂鸣器通过方波来控制蜂鸣器音调,通过方波个数控制蜂鸣器鸣笛时间长短,在使用蜂鸣器前记得先执行断开蜂鸣器的代码。
void BUZZER_BEEP1(u16 s){ //蜂鸣器响一声
u16 i;
for(i=0;i<200;i++){
GPIO_WriteBit(GPIOx,GPIO_Pin_x,(BitAction)(0)); //蜂鸣器导通
delay_us(500); //延时,两段延时之和控制频率周期长度,控制音调。而占空比控制响度。
GPIO_WriteBit(GPIOx,GPIO_Pin_x,(BitAction)(1)); //蜂鸣器断开
delay_us(500); //延时
//这里两个delay控制
}
}
蜂鸣器播放MIDI音乐:
MIDI乐谱数据定义(假设20个音符):
uc16 music1[40] = { //假定music1[偶数下标] 表示音符频率(单位Hz),music1[奇数下表] 表示持续时间(单位ms),这里定375ms为一拍
330,750, // 330作为频率,对应低音3 750 = 375*2,对应2拍
440,375,
494,375,
523,750,
//以下省略剩下的MIDI乐谱数据
}
演奏乐谱:
void MIDI_PLAY(void){ //演奏函数
u16 i,e;
for(i=0;i<20;i++){ //外循环遍历音符和节拍
for(e=0;e<music1[i*2]*music1[i*2+1]/1000;e++){ //频率*时间=总周期数,除以1000是因为表示持续时间的单位是ms,而表示频率的单位是Hz。内循环对应控制持续时间
//以下为一个周期对蜂鸣器的操作
GPIO_WriteBit(GPIOx,GPIO_Pin_x,(BitAction)(0)); //蜂鸣器导通
delay_us(500000/music1[i*2]); //因为后面还有另一半。所以t = 0.5s/f,得到一个音调对应的半个频率周期时长(即一个频率周期高电平时间),然后换算成us要乘1000000。
GPIO_WriteBit(GPIOx,GPIO_Pin_x,(BitAction)(1)); //蜂鸣器断开
delay_us(500000/music1[i*2]); //一个频率周期低电平时间,和前面另一半的0.5s组成一个1s
}
}
}
附加
STM32数据类型
u32 //定义32位无符号变量
u16 //定义16位无符号变量
u8 //定义8位无符号变量
vu32 //定义32位无符号易变变量 v相当于volatile
vu16 //定义16位无符号易变变量 v相当于volatile
vu8 //定义8位无符号易变变量 v相当于volatile
uc32 //定义32位无符号常量 c相当于const
uc16 //定义16位无符号常量 c相当于const
uc8 //定义8位无符号常变量 c相当于const
//常量是存在Flash里面的!