搭建环境
1 安装应用程序 (不使用自带的程序包)
2 安装芯片包
寄存器点灯
编写程序
main.c
#include "stm32f10x.h"
void SystemInit()
{
//编译器不报错
}
int main()
{
//1.使能GPIOC的时钟 起初地址 0x4002 1000
RCC_APB2 |= 0x01 << 4;
//2.配置GPIOC13为输出模式 0x4001 1000 + 0x04
GPIO_MODE |= 0x01 <<20;
//3.配置GPIOC13为输出低电平 0x4001 1000 + 0Ch
GPIO_SPEED &=~(0x01 << 13);
}
/* |= 或操作 拉高其它位不变
0000 1000
xxxx xxxx
1
&=~ 与操作 拉低其它位不变
0001 0000 0000
1110 1111 1111
xxxx xxxx xxxx
0
*/
stm32f10x.h
#define RCC_APB2 *( unsigned int *)0x40021018
#define GPIO_MODE *( unsigned int *)0x40011004
#define GPIO_SPEED *( unsigned int *)0x4001100c
烧录程序
接线:
tx 接 PA10
rx 接 PA9
下载时 接线端子是boot 0 接到 1
运行时 移回位
用FlyMcu 烧录
没烧录成功按下复位键
运行结果
固件库点灯(闪烁)
STM32的8种GPIO输入输出模式
上拉电阻:把不确定的信号通过电阻连接到高电平电信号转换为高电平
下拉电阻:把不确定的信号通过电阻连接到低电平电信号转换为低电平
上拉输入(GPIO_Mode_IPU):默认情况下输入引脚为1 高电平
下拉输入(GPIO_Mode_IPD):默认情况下输入引脚为0 低电平
浮空输入GPIO_Mode_IN_FLOATING):引脚不接高电平也不接低电平 即输入引脚浮空
模拟输入(GPIO_Mode_AIN):模拟输入是指传统方式的输入,数字输入是输入PCM数字信号,即0,1的二进制数字信号,通过数模转换
开漏输出(GPIO_Mode_Out_OD):输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行
开漏复用功能(GPIO_Mode_AF_OD):可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)
推挽式输出(GPIO_Mode_Out_PP):可以输出高,低电平,连接数字器件;推挽结构一般是指两个三级管分别受到互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由IC的电源低定。
推挽式复用功能(GPIO_Mode_AF_PP):可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)
固件库点灯实现闪烁
main.c
#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
void delay(uint16_t time) // 延时函数
{
uint16_t i=0;
while(time--)
{
i = 12000;
while(i--);
}
}
int main(void)
{
LED_Iint();
usart_init();
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
while(1)
{
GPIO_SetBits(GPIOC, GPIO_Pin_13);
delay(1000);
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
delay(1000);
}
}
led.c
#include "led.h"
#include "stm32f10x.h"
void LED_Iint(void)
{
GPIO_InitTypeDef led_init;
//1. 使能APB2的时钟GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
//2.结构体配置
led_init.GPIO_Mode = GPIO_Mode_Out_PP;
led_init.GPIO_Pin = GPIO_Pin_13;
led_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &led_init);
}
振动传感器控制灯的亮灭
main.c
#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exit.h"
void delay(uint16_t time) // 延时函数
{
uint16_t i=0;
while(time--)
{
i = 12000;
while(i--);
}
}
int main(void)
{
LED_Iint();
Realy_init();
Shake_init();
exit_init();
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 指示灯亮
GPIO_SetBits(GPIOA, GPIO_Pin_3); // 初始继电器关
while(1)
{
if( GPIO_ReadInputDataBit( GPIOA, GPIO_Pin_1) == 0)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_3);
delay(10000);
GPIO_SetBits(GPIOA, GPIO_Pin_3);
}
else
{
GPIO_SetBits(GPIOA, GPIO_Pin_3);
}
}
}
relay.c
#include "relay.h"
#include "stm32f10x.h"
void Realy_init(void)
{
GPIO_InitTypeDef Realy_init ;
//1.打开继电器的A时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
// 2.结构体的配置
Realy_init.GPIO_Mode = GPIO_Mode_Out_PP;
Realy_init.GPIO_Pin = GPIO_Pin_3;
Realy_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &Realy_init);
}
shake.c
#include "shake.h"
#include "stm32f10x.h"
void Shake_init(void)
{
GPIO_InitTypeDef Shake_init ;
//1.打开震动传感器的A时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
// 2.结构体的配置
Shake_init.GPIO_Mode = GPIO_Mode_IPD;
Shake_init.GPIO_Pin = GPIO_Pin_1;
Shake_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &Shake_init);
}
外部中断
中断就是指CPU正在执行一项任务A,然后突然停止任务A去执行任务B,执行完任务B再回来继续执行任务A的过程。
例如:你正在看电视,然后电话响了,你就停止看电视,跑去接电话,接完电话后由回来继续看电视。这个过程叫中断。
中断的作用
1.中断能让CPU同时执行多项任务,例如CPU在执行流水灯程序,就无法执行 按下按键时,蜂鸣器发声了。
2.当然上面的例子可以用软件轮询检擦案件是否按下来实现,但这样就消耗了CPU一部分资源来轮询检测 按键是否有按下了,所以中断的另一个优点就是
节省CPU资源
通过外部中断实现震动点灯
main.c
#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exit.h"
void delay(uint16_t time) // 延时函数
{
uint16_t i=0;
while(time--)
{
i = 12000;
while(i--);
}
}
int main(void)
{
LED_Iint();
Realy_init();
Shake_init();
exit_init();
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 指示灯亮
GPIO_SetBits(GPIOA, GPIO_Pin_3); // 初始继电器关
while(1)
{
}
}
void EXTI1_IRQHandler(void)
{
if( EXTI_GetITStatus( EXTI_Line1) != RESET)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_3);
delay(1000);
GPIO_SetBits(GPIOA, GPIO_Pin_3);
}
EXTI_ClearFlag( EXTI_Line1);
}
exit.c
#include "exit.h"
#include "stm32f10x.h"
void exit_init(void)
{
GPIO_InitTypeDef Shake_init ;
EXTI_InitTypeDef Exit_init;
NVIC_InitTypeDef Nvic_init;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 1.配置GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE );
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
Shake_init.GPIO_Mode = GPIO_Mode_IPD;
Shake_init.GPIO_Pin = GPIO_Pin_1;
Shake_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &Shake_init);
// 2.配置GPIO外部中断
Exit_init.EXTI_Line = EXTI_Line1;
Exit_init.EXTI_Mode = EXTI_Mode_Interrupt;
Exit_init.EXTI_Trigger = EXTI_Trigger_Falling;
Exit_init.EXTI_LineCmd = ENABLE;
EXTI_Init(&Exit_init);
// 3.配置NVIC中断控制器
Nvic_init.NVIC_IRQChannel = EXTI1_IRQn;
Nvic_init.NVIC_IRQChannelSubPriority = 1 ;
Nvic_init.NVIC_IRQChannelPreemptionPriority = 1;
Nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&Nvic_init);
}