本人以前学过51单片机,知道ARM这个东西后一直向往,最近终于入手一块“战舰V3 精英板”(买板子的时候,没注意看板子资源,看到“精英”二字,以为是STM32F103ZET6板子里面最牛的,而且看价格还不是最贵的,果断买了精英板),经过几天的C语言学习、keil安装及使用学习、Jlink使用学习、工程模板(基于固件库)建立……我的STM32学习终于走上正轨。之前听过别人分享如何学习STM32,其中强调了一点,就是加入一个论坛,在论坛中跟大家一起学习,共同进步,于是今天就开贴(以前水过,从来没发过贴),从零开始学习STM32(以前学过51,但是没了解过STM32,不知道算不算从零开始),记录我的学习历程,记录一个系统性地学习STM32的过程,以求跟坛友共同进步,同时以后传递给别人准备学STM32的人一些经验。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
学习了嵌套向量中断后,对自己昨天的串口初始化程序作了代码补充和注释补充,加深了对串口配置和嵌套向量中断配置的了解;
代码修改为如下,在板子上跑了一会没有发现问题:
[mw_shl_code=applescript,true]void UART_Init(u32 baud)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA , ENABLE); // 使能USART1、PA时钟
// 初始化串口的GPIO口
// USART1_TX -> GPIOA.9;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //模式设置为复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART1_RX -> GPIOA.10;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //模式设置为浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化串口1
USART_InitStructure.USART_BaudRate = baud; // 波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长:8b
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位:1
USART_InitStructure.USART_Parity = USART_Parity_No; // 奇偶校验位:无
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制:无
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收、发
// USART_DeInit(USART1); // 复位串口1
USART_Init(USART1, &USART_InitStructure); // 初始化串口1
// 开启串口1接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口1中断
// 开启串口1
USART_Cmd(USART1, ENABLE); // 使能串口1
// Usart1 NVIC 配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 优先级分组位长度模式2:先占优先级 2 位,从优先级 2 位
// 如果在其他地方配置过NVIC_PriorityGroup,则不用在这里配置
// 配置串口1中断
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 选择串口1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器
} [/mw_shl_code]
【2016-03-13】原子SYSTEM->usart.c使用和外部中断使用
外部中断配置过程:
①初始化想要映射的IO口为输入;
②开启AFIO功能复用IO时钟;
③将外部中断映射到具体的IO口;
④根据对应中断初始化EXTI寄存器;
⑤根据对应中断初始化NVIC寄存器;
⑥编写对应的中断服务函数;
本次学习中遇到过的问题:
①没有开启AFIO功能复用IO时钟;
②没有了解外部中断/事件线路映像;
1、查看板子电路图,物 {MOD}作为外部中断的IO口;
2、查看库函数指南、参考手册对应的内容,查看原子的例程并理解过程;
3、复制自己的串口工程(里面使用了SYSTEM文件夹里的usart.c,还包含以前自己写的LED,BEEP,KEY),写代码;
4、仿真调试,思考总结,记录发帖;
1、查看板子电路图,物 {MOD}作为外部中断的IO口;
就选择按键KEY0和KEY1所连接的IO口作为外部中断源;
2、查看库函数指南、参考手册对应的内容,查看原子的例程并理解过程;
外部中断配置过程:
①初始化想要映射的IO口为输入;
②开启AFIO功能复用IO时钟;
③将外部中断映射到具体的IO口;
④根据对应中断初始化EXTI寄存器;
⑤根据对应中断初始化NVIC寄存器;
⑥编写对应的中断服务函数;
3、复制自己的串口工程(里面使用了SYSTEM文件夹里的usart.c,还包含以前自己写的LED,BEEP,KEY),写代码;
串口直接使用SYSTEM文件夹里的usart.c;
然后按照外部中断配置步骤编写exti.c:
[mw_shl_code=applescript,true]#include "exti.h"
#include "stm32f10x_exti.h"
#include "key.h"
#include "usart.h"
#include "led.h"
#include "delay.h"
u8 state = 0;
void BOARD_EXTI_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟
// 初始化外部中断EXTI寄存器
// KEY0 -> PE4 -> EXTI4;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4); // 外部中断4映射到PE4
EXTI_InitStructure.EXTI_Line = EXTI_Line4; // 外部中断4
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 设置为中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 设置为下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 开启中断
EXTI_Init(&EXTI_InitStructure);
// KEY1 -> PE3 -> EXTI3;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3); // 外部中断3映射到PE3
EXTI_InitStructure.EXTI_Line=EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
// 配置外部中断NVIC寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; // 外部中断3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; // 子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; // 外部中断4
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; // 子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
NVIC_Init(&NVIC_InitStructure); // 根据指定的参数初始化VIC寄存器
}
// 外部中断3中断服务函数
// KEY1 -> PE3 -> EXTI3;
void EXTI3_IRQHandler(void)
{
delay_ms(5);
if(KEY1 == 0)
{
EXTI->IMR = 0x0;// 屏蔽外部中断
state = EXTI3_TRIGGER;
}
else
;
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志
}
// 外部中断4中断服务函数
// KEY0 -> PE4 -> EXTI4;
void EXTI4_IRQHandler(void)
{
delay_ms(5);
if(KEY0 == 0)
{
EXTI->IMR = 0x0; // 屏蔽外部中断
state = EXTI4_TRIGGER;
}
else
;
EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志
}
[/mw_shl_code]
然后为其写一个exti.h:
[mw_shl_code=applescript,true]#ifndef __EXTI_H
#define __EXTI_H
#include "sys.h"
#define NO_TRIGGER 0
#define EXTI3_TRIGGER 1
#define EXTI4_TRIGGER 2
extern u8 state;
void BOARD_EXTI_Init(void);
#endif
[/mw_shl_code]
IO口初始化就在key.c的KEY_Init函数里初始化了;
最后main.c这样写:
[mw_shl_code=applescript,true]#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "usart.h"
#include "delay.h"
#include "exti.h"
#include "key.h"
int main(void)
{
u8 already_printf = 0;
LED_Init();
BEEP_Init();
KEY_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200);
delay_init();
BOARD_EXTI_Init();
// 初始化成功提示
LED1 = 0;
BEEP = 1;
delay_ms(100);
// LED0 = 0;
LED1 = 1;
BEEP = 0;
printf(" 请按键触发中断 ");
while(1)
{
switch(state)
{
case NO_TRIGGER:
EXTI->IMR |= (1<<3)|(1<<4);
LED0 = 0;
LED1 = 0;
already_printf = 0;
break;
case EXTI3_TRIGGER:
LED0 = 0;
LED1 = 1;
if(already_printf ==0)
{
already_printf = 1;
printf(" 触发外部中断3,已锁定为EXTI3_TRIGGER状态,请发送任意字符加回车返回初始状态 ");
break;
}
else if(USART_RX_STA&0x8000)
{
printf(" 发送成功,返回初始状态... ");
printf(" 已返回初始状态,请按键触发中断 ");
state = NO_TRIGGER;
USART_RX_STA &= 0x0;
break;
}
else
{
break;
}
case EXTI4_TRIGGER:
LED0 = 1;
LED1 = 0;
if(already_printf ==0)
{
already_printf = 1;
printf(" 触发外部中断4,已锁定为EXTI4_TRIGGER状态,请发送任意字符加回车返回初始状态 ");
break;
}
else if(USART_RX_STA&0x8000)
{
printf(" 发送成功,返回初始状态... ");
printf(" 已返回初始状态,请按键触发中断 ");
state = NO_TRIGGER;
USART_RX_STA &= 0x0;
break;
}
else
{
break;
}
default:
LED0 = 1;
LED1 = 1;
printf(" 进入未知状态,1秒后强制跳转到初始状态... ");
delay_ms(1000);
printf(" 已返回初始状态,请按键触发中断 ");
state = NO_TRIGGER;
break;
}
}
}
[/mw_shl_code]
4、仿真调试,思考总结,记录发帖;
调试的结果,预想的是,在初始状态可以按键触发外部中断,进入中断后屏蔽所有外部中断,不能再触发,然后串口向板子发送一个回车后再次进入初始状态,可以继续按键触发对应中断;
这次由于资料没看全,导致时钟和中断映射没有配好(开始是以为IO口能作为任意一号外部中断,想把PE4、PE3分别作为外部中断0和1,可是怎么也找不到映射到0和1的函数或者寄存器),后面看了教程后,才知道自己没有去看外部中断的映射方式;将所有需要配置的内容配置好了之后,程序运行正常,运行结果是自己预想的;
一周热门 更多>