2021-12-7 09:12:38
指令模式前提
1. SysTick定时器
2.串口中断
3.指令对应功能的配置
之前学习51单片机是在C语言中文网看到有50单片机的串口指令模式的教程,所以我在STM32上要做了一个,指令模式有个好处,就是之后方便调试各项功能。
前提
1. SysTick定时器
#include "def.h"
__IO uint32_t mTime;
/*函数名:Deley_Init
功 能:初始化SysTick定时器
备 注:调用函数 SysTick_Config(uint32_t ticks) (默认不分频)
该函数作用:1.初始化SysTick (uint32_t ticks为重装值)
2.打开SysTick
3.打开SysTick中断并设置中断优先级(最低)
4.返回一个值(0代表成功 1代表失败)
调用函数 SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
该函数作用:配置时钟来源(注意调用顺序 先调用SysTick_Config(uint32_t ticks)
再调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)) */
void Deley_Init(void){
SysTick_Config(9000);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}
/*函数名:Deley
功 能:延时函数
备 注:调用即可精准延时*/
void Deley(__IO uint32_t time){
mTime=time;
while(mTime > 0);
}
/*函数名:Deley_D
功 能:
备 注:在中断函数SysTick_Handler(void)中调用本函数,
SysTick_Handler(void) 函数在源文件stm32f10x_it中*/
void Deley_D(void){
if(mTime>0)
mTime--;
}
头文件:
#ifndef __DEF_H
#define __DEF_H
#include "stm32f10x.h"
void Deley_Init(void);
void Deley(__IO uint32_t time);
void Deley_D(void);
#endif
注意:定义mTime时一定要在前面加上 __IO 不然无法延时, __IO 的意思是告诉编辑器不要对这个变量进行优化,他在标准库里的定义 具体可以百度
#define __IO volatile !< defines 'read / write' permissions */
函数Deley_D(void)要在SysTick_Handler(void)中调用,源文件名:stm32f10x_it.c
如下:
**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
Deley_D(); //延时函数
Judge_ETB(); //判断是否接收完一帧数据
}
2.串口中断
#include "usart.h"
__IO uint8_t CocheData[64]; //临时数据缓存
__IO uint8_t count=0; //接收计数
__IO uint8_t TimeLag = 0; //数据帧判断时间
__IO uint8_t FLAG_USART1_IT=0; //串口1中断标志 表示接收到数据 0表示未中断,1表示发生中断
__IO uint8_t FLAG_FrameData = 0; //用来表示一帧数据接收完成
/*串口1初始化函数*/
void init_usart1() {
GPIO_InitTypeDef GPIOA_InitStructure; //定义GPIOA初始化结构体变量
USART_InitTypeDef USART_InitStructure; //定义串口初始化结构体变量
NVIC_InitTypeDef NVIC_InitStructure; //定义中断初始化结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//ENABLE THE GPIOA 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//ENABLE USART1 使能串口1时钟
GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_9; //启用GPIOA Pin9引脚 串口发送引脚
GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //工作模式 复用推挽输出
GPIOA_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //工作频率50MHz
GPIO_Init(GPIOA, &GPIOA_InitStructure); //初始化GPIOA
GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_10; //启用GPIOA Pin10引脚 串口接收引脚
GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //工作模式 悬空输入
GPIO_Init(GPIOA, &GPIOA_InitStructure); //初始化GPIO
USART_InitStructure.USART_BaudRate = 115200; //设置串口1的波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置数据长度
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置停止位为1位
USART_InitStructure.USART_Parity = USART_Parity_No; //设置奇偶校验为无校验
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //启用接收和传输模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //设置硬件流模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能串口1中断
USART_ClearFlag(USART1, USART_IT_RXNE); //清除接收缓存非空
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //指定串口1的中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中断优先级
NVIC_Init(&NVIC_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //中断优先级分组
}
/*发送单个字节*/
void USART1_SendChar(uint8_t dat){
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET){ //判断发送缓存区是否为空 TXE是发送缓存区清空标志
}
USART_SendData(USART1,dat);
}
/*发送多个字节*/
void USART1_SendMulti(uint8_t *dat,uint8_t len){
uint8_t i;
for(i=0;i
USART1_SendChar(*dat++);
}
}
/*发送字符串*/
void USART1_SendString(uint8_t *dat) {
while (*dat != '