目录
0\ 因咸鱼上超低价买的板子的核心板有点问题,所以不得不先用正点的mini了之后再换回洋桃,(其实是没有问题的,因为我没有编译直接下载,屮浪费了我好长时间)
一、 STLINK(jtag)下载
- 注意PB3、4,PA14、15、13没有复用为其他功能
- 下载前一定要先编译,不然下的是之前的!!!!!!!!!!!!!!!
二、点灯
/* 首先在rcc.h中找到开启所用到的时钟所用到的函数,开启时钟(主要用到AHB、APB2、APB1)
然后同理根据库函数配置GPIO并定义用到的结构体。
*/
int main(void)
{
// Led_Init();
GPIO_InitTypeDef GPIO_InitStructure;//定义结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出负载能力更强
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
while(1){
GPIO_WriteBit(GPIOB,GPIO_Pin_1,(BitAction)(1)); //LED1接口输出高
}}
三、滴答定时器(计数到0时申请中断)
-
SysTick叫做系统滴答时钟、系统定时器,属于Cortex-M3内核中的一个外设(外围设备),被捆绑在NVIC(中断)中,用来产生SYSTICK异常(异常号:15)
-
当SysTick是一个24bit 向下递减的计数器,计到0时,从RELOAD寄存器中自动装载定时初值。
-
自动重装载
-
SysTick定时器和普通定时器在STM32微控制器中有一些明显的区别,主要体现在以下几个方面:
1.内置位置和用途:
2.SysTick定时器:SysTick是STM32微控制器内置的一个系统级定时器,专门用于提供系统级的时基和延时功能。它不依赖于外部时钟源,而是使用系统的主时钟(通常是AHB时钟)作为时钟源。
3.普通定时器:普通定时器(如TIM1、TIM2等)是专门设计用于生成PWM信号、测量脉冲宽度、产生定时中断等应用的定时器。它们可以选择多种时钟源,并且具有更灵活的定时功能和计数器控制。4.功能和应用场景:
5.SysTick定时器:主要用于实现操作系统的时基管理、延时函数的实现等。它通常用于生成固定周期的中断,作为系统的基础定时器。
6.普通定时器:用于更复杂的定时任务,例如PWM输出控制、捕获外部信号、生成特定频率的时钟等。它们的功能更加多样化和灵活,可以根据具体需求配置不同的模式和计数器设置。7.中断优先级:
8.SysTick定时器:SysTick定时器的中断具有固定的优先级,通常比其他普通定时器的中断优先级更高。这使得它特别适合于系统级的基本任务管理,例如操作系统的任务调度。
9.普通定时器:普通定时器的中断优先级可以根据应用需求进行配置,更适合于特定的定时和计数功能。10.配置和使用:
11.SysTick定时器:配置简单,通常通过调用一次SysTick_Config函数完成初始化,设置一个固定的中断周期。它的主要功能是提供基本的定时功能,适用于简单的时基管理和延时需求。
12.普通定时器:配置相对复杂,需要根据具体的应用需求选择时钟源、模式、计数器设置等。普通定时器更适合于需要更精确的定时和计数功能的场合。总结来说,SysTick定时器是STM32中的一个基础系统定时器,专注于提供系统级的基本定时功能和延时功能;而普通定时器则更灵活多样,适合于复杂的定时和计数任务。选择使用哪种定时器取决于具体的应用需求和功能要求。
#include "stm32f10x.h"
static volatile uint32_t msTicks; // 全局变量,用于存储毫秒计数
// SysTick中断处理函数
void SysTick_Handler(void)
{
msTicks++; // SysTick定时器每计满1毫秒,msTicks加1
}
// 初始化SysTick定时器
void SysTick_Init(void)
{
SysTick_Config(SystemCoreClock / 1000); // 设置每隔1毫秒触发一次SysTick中断
}
// 延时函数,延时指定的毫秒数
void Delay_ms(uint32_t ms)
{
uint32_t start = msTicks; // 记录延时开始时的毫秒计数值
while ((msTicks - start) < ms)
{
// 等待,直到msTicks增加到需要的延时毫秒数
}
}
int main(void)
{
// 初始化SysTick定时器
SysTick_Init();
while (1)
{
// 在这里可以调用Delay_ms函数进行延时
Delay_ms(1000); // 延时1秒钟
// 这里是需要执行的主程序代码
}
}
四、GPIO作输入
int main (void){//主程序
// RCC_Configuration();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIOA_ST;GPIO_InitTypeDef GPIOB_ST;
GPIOB_ST.GPIO_Mode= GPIO_Mode_Out_PP ;
GPIOB_ST.GPIO_Speed = GPIO_Speed_50MHz;
GPIOB_ST.GPIO_Pin=GPIO_Pin_0;
GPIOA_ST.GPIO_Mode= GPIO_Mode_IPU;
GPIOA_ST.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIOA_ST);
GPIO_Init(GPIOB,&GPIOB_ST);
while(1){
if( !GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)){
delay_ms(20);
// GPIO_SetBits(GPIOB,GPIO_Pin_0);不如writebit灵活
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)){}
GPIO_WriteBit( GPIOB,GPIO_Pin_0 , (BitAction) (1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_0)));
}
}
}
五、FLASH
- 实际调运库函数实现很简单
//读取
uint32_t MyFLASH_ReadWord(uint32_t Address )
{
return *((volatile u32 *)(Address));
}
uint16_t MyFLASH_ReadHalfWord(uint32_t Address )
{
return *((volatile u16 *)(Address));
}
uint8_t MyFLASH_ReadByte(uint32_t Address )
{
return *((volatile u8 *)(Address));
}
//闪存擦除(前后开关锁)
void MyFLASH_ErasePage(u32 Page_Address )
{
FLASH_Unlock();
FLASH_ErasePage(Page_Address);//or FLASH_EraseAllPages();
FLASH_Lock();
}
//写入字/半字(前后开关锁)
void MyFLASH_Write(u32 Address, u32 Data)
{
FLASH_Unlock();
FLASH_ProgramWord(Address, Data);//FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
写入半字时高4位为FFFF低4位为写入数据
FLASH_Lock();
}
- STM32微控制器中的“半字”(Half-word)通常指的是16位(2字节)的数据类型。在STM32系列中,内存中的数据通常以字(Word)为单位进行存储和访问,一个字是32位(4字节)。因此,STM32中的半字实际上是指两个字节的数据,因为微控制器的内存和总线结构是按照字节寻址的,所以即使你在程序中只使用了16位数据类型,它也会占用2个字节的存储空间。
//写入前先要擦除
u16 Store_Data[512];
void Store_Init(void)//每次重新上电后都会通过此函数向Sram传输储存的数据
{ if(MyFLASH_ReadHalfWord(0x0800FC00)!=0xA5A5)//确保第一次未存入数据时
{
MyFLASH_ErasePage( 0x0800FC00);//调用擦除,然后写入标志位
MyFLASH_Write(0x0800FC00,0xA5A5);
for(u16 i=1 ;i<512;i++)//将数据存入flash
{
MyFLASH_Write(0x0800FC00+i*2,0x0000);//确保没用到的也都置为0
}
}
for(u16 i=0 ;i<512;i++)//将数据传给SRAM
{
Store_Data[i]= MyFLASH_ReadHalfWord(0x0800FC00+i*2);
}
}
void Store_Save(void)
{
MyFLASH_ErasePage(0x0800FC00);
for(u16 i=0 ;i<512;i++){
MyFLASH_Write(0x0800FC00+i*2,Store_Data[i]);//Store_Data[0]为标志位不能使用
}
}
六、蜂鸣器驱动
- 确保结束时为高电平状态,防止三极管一直导通烧坏蜂鸣器。