《STM32学习笔记》3——核心功能电路与编程(上)

接上文,文中的图片,大多数来自视频的截图(来自洋桃电子)。
欢迎大家批评指正!

STM32学习笔记-专栏

一、核心板电路分析

洋桃核心板

二、点灯 LED

1、LED电路

2、LED功能相关初始化配置

  • GPIO 初始化配置
    • 结构体声明—— IO端口号、IO端口速度、IO端口模式
    • 时钟启动 IO端口——APB2 高速总线启动 GPIOA、GPIOB、GPIOC
    • 设置 IO端口号(宏定义)
    • 配置 IO工作模式——开漏输出、推挽输出
    • 配置 IO端口速度(仅输出模式下需要配置)
    • 运行 GPIO 的初始化库函数,将上述配置写入 IO端口组的寄存器
void LED_Init(void){											 //LED灯的接口初始化
   GPIO_InitTypeDef  GPIO_InitStructure; 	
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);       
   GPIO_InitStructure.GPIO_Pin = LED1 | LED2; 					//选择端口号(0~15或all)                        
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 			//选择IO接口工作方式       
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 			//设置IO接口速度(2/10/50MHz)    
   GPIO_Init(LEDPORT, &GPIO_InitStructure);			
}

3、LED功能封装函数介绍

视频中,将LED功能封装成了特定函数。(即固件库GPIO功能函数)

3.1 方法1
  • GPIO_WriteBit —— 对端口进行写操作,函数参数为 端口组、端口名、位控制。
3.2 方法2
每隔500ms,翻转LED1的电平。
  • GPIO_ReadOutputDataBit —— 读取端口输出值
3.3 方法3

两函数的参数均只有两个,端口组、端口名

  • GPIO_SetBits —— 端口置1(拉高)
  • GPIO_ResetBits —— 端口清零(拉低)
3.4 方法4

对端口组赋值的函数,参数为端口组、4位十六进制数
GPIO_Write —— 对端口组赋十六进制数,给16个端口各自赋值

3.5 方法5

以上是以固件库函数控制。
这里使用多层宏定义,直接控制端口。
如 : PB(1)=1;PB1端口直接赋值,很方便易懂。

4、闪灯和呼吸灯

包含 delay.c delay.h ,调用延时函数(滴答定时器实现,精准延时)

4.1 延时函数
#define AHB_INPUT  72                   //请按RCC中设置的AHB时钟频率填写到这里(单位MHz)

void delay_us(u32 uS)
{                                       //uS微秒级延时程序(参考值即是延时数,72MHz时最大值233015)	
	SysTick->LOAD=AHB_INPUT*uS;         //重装计数初值(当主频是72MHz,72次为1微秒)
	SysTick->VAL=0x00;                  //清空定时器的计数器
	SysTick->CTRL=0x00000005;           //时钟源HCLK,打开定时器
	while(!(SysTick->CTRL&0x00010000)); //等待计数到0
	SysTick->CTRL=0x00000004;           //关闭定时器
}
4.2 呼吸灯

延时控制亮度——占空比思想(视觉暂留)
高频切换亮灭,可以发现灯不闪,而是变暗。亮度则由亮灭延时的比例决定。

呼吸灯逐渐变亮:

for(i = 0; i < 10; i++)
{
   GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1));        //LED1接口输出高电平1
   delay_us(t);                                       //延时
   GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0));        //LED1接口输出低电平0
   delay_us(501-t);                                   //延时
}
t++;

5、按键控制灯

还是GPIO相关。

5.1 初始化

配置模式为读取IO状态

void KEY_Init(void)
{                                                     //微动开关的接口初始化
	GPIO_InitTypeDef  GPIO_InitStructure;             //定义GPIO的初始化枚举结构	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       
    GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2;        //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     //选择IO接口工作方式 //上拉电阻       
	GPIO_Init(KEYPORT,&GPIO_InitStructure);			
}
5.2 例子1 无锁存
if(GPIO_ReadInputDataBit(KEYPORT,KEY1))         //读按键接口的电平
   { 
      GPIO_ResetBits(LEDPORT,LED1);             //LED灯都为低电平(0) 
   }
else
   {	
      GPIO_SetBits(LEDPORT,LED1);               //LED灯都为高电平(1) 
   }
  • GPIO_ReadInputDataBit —— 读取端口输入
5.3 例子2 无锁存
GPIO_WriteBit(LEDPORT,LED1,(BitAction)(!GPIO_ReadInputDataBit(KEYPORT,KEY1))); 

效果同上

5.4 例子3 有锁存
if(!GPIO_ReadInputDataBit(KEYPORT,KEY1))                                                 //读按键接口的电平
{ 
	delay_ms(20);                                                                        //延时去抖动
	if(!GPIO_ReadInputDataBit(KEYPORT,KEY1))                                             //读按键接口的电平
   { 
		GPIO_WriteBit(LEDPORT,LED1,(BitActio(1-GPIO_ReadOutputDataBit(LEDPORT,LED1)));   //LED取反
		while(!GPIO_ReadInputDataBit(KEYPORT,KEY1));                                     //等待按键松开 
	}
}
  • 按下按键时,GPIO_ReadInputDataBit(KEYPORT,KEY1) 为 0。
  • 延时消除按下的机械抖动,通常为20ms左右。
  • 通过 while循环 锁存按键状态,下次按下按键才会跳出该循环,再次进入 if,从而转换灯的状态。
5.5 例子4 有锁存
u8 a = 0; 
if(!GPIO_ReadInputDataBit(KEYPORT,KEY1))                 //读按键接口的电平
{ 
	delay_ms(20);                                        //延时20ms去抖动
	if(!GPIO_ReadInputDataBit(KEYPORT,KEY1))             //读按键接口的电平
    {                                                    //在2个LED上显示二进制加法		
	   a++;                                              //变量加1
	   if(a>3)
       {                                                 //当变量大于3时 清0
	      a=0; 
	   }
	   GPIO_Write(LEDPORT,a);                            //直接数值操作将变量值写入LED(LED在GPIOB组的PB0和PB1上)
	   while(!GPIO_ReadInputDataBit(KEYPORT,KEY1));      //等待按键松开 
	 }
}
  • 以 a 的值赋给端口组,实现 “仅D1亮、仅D2亮、都亮、都灭” 的循环。

三、FLASH 读写程序

FLASH 可以实现掉电不丢失。

1、 FLASH.c 文件:

#include "flash.h"

//FLASH写入数据
void FLASH_W(u32 add,u16 dat)
{                                                                                            //参数1:32位FLASH地址。参数2:16位数据
 	 RCC_HSICmd(ENABLE);                                                                     //打开HSI时钟
	 FLASH_Unlock();                                                                         //解锁FLASH编程擦除控制器
     FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);    //清除标志位
     FLASH_ErasePage(add);                                                                   //擦除指定地址页
     FLASH_ProgramHalfWord(add,dat);                                                         //从指定页的addr地址开始写
     FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);    //清除标志位
     FLASH_Lock();                                                                           //锁定FLASH编程擦除控制器
}

//FLASH读出数据
u16 FLASH_R(u32 add)
{                             //参数1:32位读出FLASH地址。返回值:16位数据
	u16 a;
    a = *(u16*)(add);         //从指定页的addr地址开始读
return a;
}
  • RCC_HSICmd(ENABLE); //打开HSI时钟 例子中注释掉了这句,因为前面已经打开了HSI。
  • 擦除只能以页擦除。
    F103对应:

2、固件库中相关函数

3、前操作及初始化

  • 定义写入地址 #define FLASH_START_ADDR 0x0801f000 //写入的起始地址
  • 时钟等初始化
  • 在while循环前,指定页地址读FLASH 。 a = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH
  • 注意写入数据大小,留足空白位置

4、main 函数

在需要的位置写入

5、注意

  • 操作一定要先擦后写。
  • 每页是1024个地址,起始地址Ox08000000
  • 擦除操作以页为单位,写操作则必须以16位宽度为单位,允许跨页写入。
  • STM32内置FLASH擦或写时,必须打开外部/内部高速振荡器。
  • FLASH可多次擦写10万次,不可死循环擦写。
  • 擦写时要避开用户程序存储区的区域,否则会擦掉用户程序导致错误。
  • 擦除一页要10ms(对于1k大小的一页),比较慢。而且不能单个字节的擦写。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

frozendure

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值