提示:今天是STM32入门学习的第三天,重点学习了优先级,串口等
目录
第一讲 C语言的复习和寄存器地址名称映射
1.C语言复习
1.1 位操作
1) 不改变其他位的值的状况下,对某几个位进行设值。
GPIOA->CRL&=0XFFFFFF0F; //将第 4-7 位清 0
GPIOA->CRL|=0X00000040; //设置相应位的值,不改变其他位的值
2) 移位操作提高代码的可读性。
3) ~取反操作使用技巧
1.2 define 宏定义
define 是 C 语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供 方便。常见的格式: #define 标识符 字符串 “标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。
例如: #define SYSCLK_FREQ_72MHz 72000000 //定义标识符 SYSCLK_FREQ_72MHz 的值为 72000000。
1.3 extern 变量申明
C 语言中 extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。这里面要注意,对于 extern 申明变量可以多 次,但定义只有一次。
在我们的代码中你会看到看到这样的语句: extern u16 USART_RX_STA; 这个语句是申明 USART_RX_STA 变量在其他文件中已经定义了,在这里要使用到。所以,你肯定 可以找到在某个地方有变量定义的语句: u16 USART_RX_STA; 的出现。下面通过一个例子说明一下使用方法。 在 Main.c 定义的全局变量 id,id 的初始化都是在 Main.c 里面进行的。
1.4 typedef 类型别名
typedef 用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。 typedef 在 MDK 用得最多的就是定义结构体的类型别名和枚举类型了。
1.5 ifdef条件编译
单片机程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。条件编译命令最常见的形式为:
#ifdef 标识符
程序段1
#else
程序段2
#endif
1.6 C语言关键字 :static
2.MDK中寄存器地址名称映射分析
2.1 51中映射方法:
sfr P0 =0x80;//P0映射到地址0x80
P0=0x00//忘寄存器地址0x80赋值0x00
0x00000000是赋值给了GPIOA的ODR寄存器地址也就是说GPIOA->ODR这种写法。
#define PERIPH_BASE ((uint32_t)0x40000000)//先找外设地址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)//再找APS2
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)//然后找那个IO口
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)//控制寄存器
第二讲 STM32 时钟系统
时钟系统是 CPU 的脉搏,就像人的心跳一样。 STM32 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就可以解决一切。 因为首先 STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及 RTC 只需要几十 k 的时钟即可。同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。
1. 时钟系统框图讲解
其中蓝色为时钟源、灰色为选择器、而PLL为锁相环主要是倍频、绿色为分屏器
在 STM32 中,有五个时钟源,为 HSI、HSE、LSI、LSE、PLL。从时钟频率来分可以分为 高速时钟源和低速时钟源,在这 5 个中 HIS,HSE 以及 PLL 是高速时钟,LSI 和 LSE 是低速时 钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时 钟源,其中 HSE 和 LSE 是外部时钟源,其他的是内部时钟源。下面我们看看 STM32 的 5 个时 钟源,我们讲解顺序是按图中红圈标示的顺序:
①HSI 是高速内部时钟,RC 振荡器,频率为 8MHz。
②HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。我们的开发板接的是 8M 的晶振。
③LSI 是低速内部时钟,RC 振荡器,频率为 40kHz。独立看门狗的时钟源只能是 LSI,同 时 LSI 还可以作为 RTC 的时钟源。
④LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。
⑤PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、HSE 或者 HSE/2。倍频可选择为2~16 倍,但是其输出频率最大不得超过 72MHz。
2. 系统时钟SYSCLK可来源于三个时钟源:
①HSI振荡器时钟
②HSE振荡器时钟
③PLL时钟
3.STM32可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。
4.任何一个外设在使用之前,必须首先使能其相应的时钟。
RCC相关的寄存器
typedef struct
{
__IO uint32_t CR; //HSI,HSE,CSS,PLL等的使能和就绪标志位
__IO uint32_t CFGR; //PLL等的时钟源选择,分频系数设定
__IO uint32_t CIR; // 清除/使能 时钟就绪中断
__IO uint32_t APB2RSTR; //APB2线上外设复位寄存器
__IO uint32_t APB1RSTR; //APB1线上外设复位寄存器
__IO uint32_t AHBENR; //DMA,SDIO等时钟使能
__IO uint32_t APB2ENR; //APB2线上外设时钟使能
__IO uint32_t APB1ENR; //APB1线上外设时钟使能
__IO uint32_t BDCR; //备份域控制寄存器
__IO uint32_t CSR; //控制状态寄存器
} RCC_TypeDef;
2.时钟配置相关函数讲解
第四讲 systeminit时钟初始化函数解析
#define SYSCLK_FREQ_72MHz 72000000
SYSCLK 72MHz
AHB 72MHz
PCLK1 36MHz
PCLK2 72MHz
PLL 72MHz
第五讲 21讲 Systick滴答定时器-延时函数讲解
第六讲 端口复用及重映射
1.端口复用功能
STM32 有很多的内置外设,这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO 如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。 这部分知识在《STM32 中文参考手册 V10》的 P109,P116~P121 有详细的讲解哪些 GPIO 管脚是 可以复用为哪些内置外设的。大家都知道,MCU 都有串口,STM32 有好几个串口。比如说 STM32F103ZET6 有 5 个串口,我 们可以查手册知道,串口 1 的引脚对应的 IO 为 PA9,PA10.PA9,PA10 默认功能是 GPIO,所以当 PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。
复用端口初始化有几个步骤:
1) GPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2) 复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3) 端口模式配置。
在 IO 复用位内置外设功能引脚的时候,必须设置 GPIO 端口的模式,至于 在复用功能下 GPIO 的模式是怎么对应的,这个可以查看手册《STM32 中文参考手册 V10》 P110 的表格“8.1.11 外设的 GPIO 配置”。这里我们拿 Usart1 举例:
从表格中可以看出,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出, RX 管脚配置为浮空输入或者带上拉输入。
我们在使用复用功能的是时候,最少要使能 2 个时钟:
1) GPIO 时钟使能 2) 复用的外设时钟使能
同时要初始化 GPIO 以及复用外设功能
2.端口重映射
为了使不同器件封装的外设 IO 功能数量达到最优,可以把一些复用功能重新映射到其他一 些引脚上。STM32 中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。我们知道每 个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计 工程师可以更好地安排引脚的走向和功能,在 STM32 中引入了外设引脚重映射的概念,即一个 外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚 映射到其它的端口。 简单的讲就是把管脚的外设功能映射到另一个管脚,但不是可以随便映射的。
具体对应关 系《STM32 中文参考手册 V10》的 P116 页“8.3 复用功能和调试配置”有讲解。这里我们同样 拿串口 1 为例来讲解。
从表中可以看出,默认情况下,串口 1 复用的时候 的引脚位 PA9,PA10,同时我们可以将 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面去。
所以重映射我们同样要使能复用功能的时候讲解的 2 个时钟外,还要使能 AFIO 功能时钟,然后 要调用重映射函数。详细步骤为:
1)使能 GPIOB 时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
2)使能串口 1 时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3)使能 AFIO 时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
4)开启重映射: GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);根据第一个参数,来确定是部分重映射还是全部重映射
这样就将串口的 TX 和 RX 重映射到管脚 PB6 和 PB7 上面了。
哪些情况需要开启AFIO辅助功能时钟
其他重映射,大家 除了查看中文参考手册之外,还可以从 GPIO_PinRemapConfig 函数入手查看第一个入口参数的 取值范围可以得知。
USART1 只有一种重映射,而对于 USART3,存在部分重映射和完全重映射。所谓部分重映射就是部分管脚和默认的是一样的,而部分管脚是重新映射到其他管脚。而完全重 映射就是所有管脚都重新映射到其他管脚。看看手册中的 USART3 重映射表:
部分重映射就是 PB10,PB11,PB12 重映射到 PC10,PC11,PC12 上。而 PB13 和 PB14 和没有重映射 情况是一样的,都是 USART3_CTS 和 USART3_RTS 对应管脚。完全重映射就是将这两个脚重新映 射到 PD11 和 PD12 上去。我们要使用 USART3 的部分重映射,我们调用函数方法为: GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
第七讲 NVIC中断优先级
1.优先级的了解
中断优先级设置的步骤:
1. 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的 分配位数。调用函数为 NVIC_PriorityGroupConfig();
2. 设置所用到的中断的中断优先级别。对每个中断调用函数为 NVIC_Init();
们总结一下 中断优先级设置的步骤: 1. 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的 分配位数。调用函数为 NVIC_PriorityGroupConfig(); 2. 设置所用到的中断的中断优先级别。对每个中断调用函数为 NVIC_Init();
终端管理:首先,对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。
分组配置是在寄存器SCB->AIRCR中配置:
通过这个表,我们就可以清楚的看到组 0~4 对应的配置关系,例如组设置为 3,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,低 1 位是 响应优先级。每个中断,你可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的 级别高于响应优先级。而数值越小所代表的优先级就越高。
2.库函数设置
通过以上介绍,我们熟悉了 STM32 中断设置的大致过程。接下来我们介绍如何使用库函 数实现以上中断分组设置以及中断优先级管理,使得我们以后的中断设置简单化。NVIC 中断 管理函数主要在 misc.c 文件里面。
首先要讲解的是中断优先级分组函数 NVIC_PriorityGroupConfig,其函数申明如下:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
这个函数的作用是对中断的优先级进行分组,这个函数在系统中只能被调用一次,一旦分 组确定就最好不要更改。这个函数我们可以找到其实现:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
从函数体可以看出,这个函数唯一目的就是通过设置 SCB->AIRCR 寄存器来设置中断优先级分 组,这在前面寄存器讲解的过程中已经讲到。而其入口参数通过双击选中函数体里面的 “IS_NVIC_PRIORITY_GROUP”然后右键“Go to defition of …”可以查看到为
#define IS_NVIC_PRIORITY_GROUP(GROUP)
(((GROUP) == NVIC_PriorityGroup_0) ||
((GROUP) == NVIC_PriorityGroup_1) || \
((GROUP) == NVIC_PriorityGroup_2) || \
((GROUP) == NVIC_PriorityGroup_3) || \
((GROUP) == NVIC_PriorityGroup_4))
分组范围为 0-4。比如我们设置整个系统的中断优先级分组值 为 2,那么方法是: NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
这样就确定了一共为“2 位抢占优先级,2 位响应优先级”。
设置好了系统中断分组,那么对于每个中断我们又怎么确定他的抢占优先级和响应优先级 呢?下面我们讲解一个重要的函数为中断初始化函数 NVIC_Init,其函数申明为: void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) 其中 NVIC_InitTypeDef 是一个结构体,我们可以看看结构体的成员变量:
typedef struct
{
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
NVIC_InitTypeDef 结构体中间有三个成员变量,这三个成员变量的作用是:
NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到 每个中断对应的名字。例如 USART1_IRQn。
NVIC_IRQChannelPreemptionPriority:定义这个中断的抢占优先级别。
NVIC_IRQChannelSubPriority:定义这个中断的子优先级别。
NVIC_IRQChannelCmd:该中断是否使能。
我们要使能串口 1 的中断,同时设置抢占优先级为 1,子优先级位 2,初始化的方法是:
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化 NVIC 寄存器
第八讲 串口通信基本原理
- 1.串行通信接口背景知识
- 2.STM32F1串口框图讲解
- 3.STM32串口常用寄存器和库函数
- 4.串口配置方法(手把手写简单的通信实例)
- 5.串口通信实验讲解
1.串行通信接口背景知识
处理器与外部设备通信的两种方式:
并行通信
- 传输原理:数据各个位同时传输。
- 优点:速度快
- 缺点:占用引脚资源多
串行通信
- 传输原理:数据按位顺序传输。
- 优点:占用引脚资源少
- 缺点:速度相对较慢
a.串行通信:按照数据传送方向,分为:
单工:数据传输只支持数据在一个方向上传输
半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
b.串行通信的通信方式
同步通信:带时钟同步信号传输。SPI,IIC通信接口
异步通信:不带时钟同步信号。UART(通用异步收发器),单总线。
2.STM32F1串口框图讲解
STM32的串口通信接口:
UART:通用异步收发器
USART:通用同步异步收发器
大容量STM32F10x系列芯片,包含3个USART和2个UART
UART异步通信方式引脚连接方法:RXD:数据输入引脚。数据接受。TXD:数据发送引脚。数据发送。
第二幅图有转换器是因为时钟脉冲可能不同。
UART异步通信方式引脚:
UART异步通信方式特点:
3.STM32串口常用寄存器和库函数
void USART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
void USART_Cmd();//使能串口
void USART_ITConfig();//使能相关中断
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
FlagStatus USART_GetFlagStatus();//获取状态标志位
void USART_ClearFlag();//清除状态标志位
ITStatus USART_GetITStatus();//获取中断状态标志位
void USART_ClearITPendingBit();//清除中断状态标志位
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
4.串口配置一般步骤(手把手写串口实例)
USART_ITConfig();
NVIC_Init();
⑥使能串口:USART_Cmd();
⑦编写中断处理函数:USARTx_IRQHandler();
⑧串口数据收发:
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
⑨串口传输状态获取:
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
#include "stm32f10x.h"
void MY_USART_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
GPIO_InitTypeDef GPIO_InitStrue;
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
USART_InitTypeDef USART_InitStrue;
USART_InitStrue.USART_BaudRate=115200;
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStrue.USART_Parity=USART_Mode_Tx;
USART_InitStrue.USART_StopBits=USART_StopBits_1;
USART_InitStrue.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStrue);
USART_Cmd(USART1,ENABLE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStruct);
}
void USART1_IRQHandler(void)
{
unsigned char res;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
res=USART_ReceiveData(USART1);
USART_SendData(USART1,res);
}
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
MY_USART_Init();
while(1);
}
5.串口通信实验讲解
SYSTEM 组下双击 usart.c,我们就可以看到该文件里面的代码, 先介绍 uart_init 函数,该函数代码如下:
//初始化 IO 串口 1
//bound:波特率
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//①串口时钟使能,GPIO 时钟使能,复用时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|
RCC_APB2Periph_GPIOA, ENABLE); //使能 USART1,GPIOA 时钟
//②串口复位
USART_DeInit(USART1); //复位串口 1
//③GPIO 端口模式设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //ISART1_TX PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX PA.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10
//④串口参数初始化
USART_InitStructure.USART_BaudRate = bound; //波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为 8 位
USART_InitStructure.USART_StopBits = USART_StopBits_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_Init(USART1, &USART_InitStructure); //初始化串口
#if EN_USART1_RX //如果使能了接收
//⑤初始化 NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级 3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //中断优先级初始化
//⑤开启中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
#endif
//⑥使能串口
USART_Cmd(USART1, ENABLE); //使能串口
}
① 串口时钟使能,GPIO 时钟使能 ② 串口复位 ③ GPIO 端口模式设置 ④ 串口参数初始化 ⑤ 初始化 NVIC 并且开启中断 ⑥ 使能串口
在 main.c 里面编写如下代码:
#include "key.h"
#include "sys.h"
#include "usart.h"
int main(void)
{
u8 t;
u8 len;
u16 times=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设 置 NVIC 中断分组 2
uart_init(115200); //串口初始化波特率为 115200
LED_Init(); //LED 端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{ len=USART_RX_STA&0x3f; //得到此次接收到的数据长度
printf("\r\n 您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{ USART_SendData(USART1, USART_RX_BUF[t]); //向串口 1 发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
//等待发送结束
}
printf("\r\n\r\n"); //插入换行
USART_RX_STA=0;
}else
{ times++;
if(times%5000==0)
{ printf("\r\n 战舰 STM32 开发板 串口实验\r\n");
printf("正点原子@ALIENTEK\r\n\r\n");
}
if(times%200==0)printf("请输入数据,以回车键结束\n");
if(times%30==0)LED0=!LED0; //闪烁 LED,提示系统正在运行.
delay_ms(10);
}
}
}