1. 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的分配位数。调用函数为 NVIC_PriorityGroupConfig();
2. 设置所用到的中断的中断优先级别。对每个中断调用函数为 NVIC_Init();
代码
uart.c文件完整代码(带注释):
#include “usart.h”
#include “sys.h”
//加入以下代码,支持print函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义__sys_exit()以避免使用半主机模式
_sys_exit(int x){
x = x;
}
//重定义fputc函数
int fputc(int ch,FILE *f){
while((USART1-》SR&0X40)==0);//循环发送直到发送完毕
USART1-》DR = (u8)ch;
return ch;
}
#endif
/*使用microLib的方法*/
/*
int fputc(int ch,FILE *f){
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,(uint8_t)ch);
return ch;
}
int GetKey (void) {
while (!(USART1-》SR & USART_FLAG_RXNE));
return ((int)(USART1-》DR & 0x1FF));
}
*/
#if EN_USART1_RX //如果使能了接收
u8 USART_RX_BUF[USART_REC_LEN];//接收缓冲区,最大USART_REC_LEN个字节。
u16 USART_RX_STA = 0;//接收状态标记
//串口状态寄存器SR在中文参考手册---P540
//对用状态的宏定义在stm32f1ox_uart.h中
//串口发送单个字节数据
void uart_send_tx(u8 ch){
USART1-》DR = (u16)ch;
while(!(USART1-》SR&USART_FLAG_TXE));
//判断这个字节是否移动到移位寄存器中,也就是判断字节数据有没有发送完成
}
//串口发送多个字节数据
void uart_send_tx_s(u8 *pString){
while(*pString != ‘ ’){
uart_send_tx(*pString++);
}
}
void uart_init(u32 bound){
//GPIO端口配置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//开启对应端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//在《STM32 中文参考手册 V10》的 P110“8.1.11 外设的 GPIO 配置”中有讲解
//USART1_TX PA.9 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//引脚pa.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率50Mhz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.9发送端
//USART1_RX PA.10 浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//引脚pa.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.10接收端
//中断配置 ------中断管理函数章节 4.5 有讲解中断管理相关的知识--P121
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 初始化设置
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);//初始化串口1
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断
USART_Cmd(USART1,ENABLE);//使能串口
}
/*******************************************************************************
void USART1_IRQHandler(void)函数是串口 1 的中断响应函数,当串口 1 发生了相应
的中断后,就会跳到该函数执行。中断相应函数的名字是不能随便定义的,一般我们都遵
循 MDK 定义的函数名。这些函数名字在启动文件 startup_stm32f10x_hd.s 文件中可以找到。
**********************************************************************************/
void USART1_IRQHandler(void){ //串口1中断服务程序
u8 Res;
if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=RESET)
//接收中断(接收到的数据必须以 0x0d 0x0a结尾)
{
Res = USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0X8000)==0){ //接收未完成
if(USART_RX_STA&0X4000){ //接收到了0x0d
if(Res!=0x0a)USART_RX_STA=0; //接收错误重新开始
else USART_RX_STA|=0X8000;//接收完成
//printf(“接收到数据!!”);
}
else//还没接收到0x0d
{
if(Res == 0x0d) //判断接收到到的数据是否为0x0d
USART_RX_STA|=0X4000;
else{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res;
USART_RX_STA++;
if(USART_RX_STA》(USART_REC_LEN-1))
USART_RX_STA=0;//接收数据错误重新开始接收
}
}
}
}
}
#endif
usart.h文件:
main#ifndef __USART_H
#define __USART_H
#include “sys.h”
#include “stdio.h”
#define USART_REC_LEN 200 //接收最大字节数为200个字节
#define EN_USART1_RX 1 //使能-1/禁止-0
extern u8 USART_RX_BUF[USART_REC_LEN];
extern u16 USART_RX_STA; //接收状态标志
void uart_init(u32 bound);//端口配置函数
void uart_send_tx(u8 ch);
void uart_send_tx_s(u8 *pString);//发送字符串函数
#endif
main.c文件
#include “sys.h”
#include “delay.h”
#include “usart.h”
#include “led.h”
int main(void )
{
u8 t = 0;
u8 len; //保存接收数据的长度
u16 times=0;
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置中断分组,在sys.c文件中,如果不设置的的化默认分组为2
uart_init(9600); //串口初始化,内含中断的初始化
LED_Init();
while(1){
if(USART_RX_STA&0X8000){ //通过自定义寄存的最高位,判断是否成功收到数据
len = USART_RX_STA&0X3FFF; //获得此次接收数据的长度,USART_RX_STA低14位是记录数据长度的。
uart_send_tx_s(“发送成功,发送的数据为:rn”);
for(t = 0;t《len;t++){
USART_SendData(USART1,USART_RX_BUF[t]); //通过库函数发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//通过获取usart1状态寄存器的第6位确定数据有没有发送成功
}
printf(“rn”); //换行
USART_RX_STA=0; //发送完成,将状态归零,准备下一次接收数据
}
else{
times++;
if(times%100==0) //1秒发送一次消息,
uart_send_tx_s(“暂无数据发送!rn”);
if(times%30==0) //0.3秒进入一次,对times求余数
LED1 = ~LED1; //闪烁led表示系统正在运行
delay_ms(10);
}
}
}
/*************************************************************、
stm32串口程序在库函数开发指南的第179页
在uart.c文件中的特殊定义:
一个接收状态寄存器 USART_RX_STA(此寄存器其实就是一个全局
变量,由作者自行添加。由于它起到类似寄存器的功能,这里暂且称之为寄存器)实现对
串口数据的接收管理。USART_RX_BUF 的大小由 USART_REC_LEN 定义,也就是一次接
收的数据最大不能超过 USART_REC_LEN 个字节。
USART_RX_STA:
bit15, 接收完成标志
bit14, 接收到0x0d
bit13~0, 接收到的有效字节数目
*************************************************************/
调试过程

完整工程
完整工程可直接编译:
程序参考正点原子编写,此文章只作为本人笔记。如对你有帮助,那真是再好不过。今天就到这里goodbye!!
1. 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的分配位数。调用函数为 NVIC_PriorityGroupConfig();
2. 设置所用到的中断的中断优先级别。对每个中断调用函数为 NVIC_Init();
代码
uart.c文件完整代码(带注释):
#include “usart.h”
#include “sys.h”
//加入以下代码,支持print函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义__sys_exit()以避免使用半主机模式
_sys_exit(int x){
x = x;
}
//重定义fputc函数
int fputc(int ch,FILE *f){
while((USART1-》SR&0X40)==0);//循环发送直到发送完毕
USART1-》DR = (u8)ch;
return ch;
}
#endif
/*使用microLib的方法*/
/*
int fputc(int ch,FILE *f){
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,(uint8_t)ch);
return ch;
}
int GetKey (void) {
while (!(USART1-》SR & USART_FLAG_RXNE));
return ((int)(USART1-》DR & 0x1FF));
}
*/
#if EN_USART1_RX //如果使能了接收
u8 USART_RX_BUF[USART_REC_LEN];//接收缓冲区,最大USART_REC_LEN个字节。
u16 USART_RX_STA = 0;//接收状态标记
//串口状态寄存器SR在中文参考手册---P540
//对用状态的宏定义在stm32f1ox_uart.h中
//串口发送单个字节数据
void uart_send_tx(u8 ch){
USART1-》DR = (u16)ch;
while(!(USART1-》SR&USART_FLAG_TXE));
//判断这个字节是否移动到移位寄存器中,也就是判断字节数据有没有发送完成
}
//串口发送多个字节数据
void uart_send_tx_s(u8 *pString){
while(*pString != ‘ ’){
uart_send_tx(*pString++);
}
}
void uart_init(u32 bound){
//GPIO端口配置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//开启对应端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//在《STM32 中文参考手册 V10》的 P110“8.1.11 外设的 GPIO 配置”中有讲解
//USART1_TX PA.9 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//引脚pa.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率50Mhz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.9发送端
//USART1_RX PA.10 浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//引脚pa.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.10接收端
//中断配置 ------中断管理函数章节 4.5 有讲解中断管理相关的知识--P121
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 初始化设置
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);//初始化串口1
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断
USART_Cmd(USART1,ENABLE);//使能串口
}
/*******************************************************************************
void USART1_IRQHandler(void)函数是串口 1 的中断响应函数,当串口 1 发生了相应
的中断后,就会跳到该函数执行。中断相应函数的名字是不能随便定义的,一般我们都遵
循 MDK 定义的函数名。这些函数名字在启动文件 startup_stm32f10x_hd.s 文件中可以找到。
**********************************************************************************/
void USART1_IRQHandler(void){ //串口1中断服务程序
u8 Res;
if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=RESET)
//接收中断(接收到的数据必须以 0x0d 0x0a结尾)
{
Res = USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0X8000)==0){ //接收未完成
if(USART_RX_STA&0X4000){ //接收到了0x0d
if(Res!=0x0a)USART_RX_STA=0; //接收错误重新开始
else USART_RX_STA|=0X8000;//接收完成
//printf(“接收到数据!!”);
}
else//还没接收到0x0d
{
if(Res == 0x0d) //判断接收到到的数据是否为0x0d
USART_RX_STA|=0X4000;
else{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res;
USART_RX_STA++;
if(USART_RX_STA》(USART_REC_LEN-1))
USART_RX_STA=0;//接收数据错误重新开始接收
}
}
}
}
}
#endif
usart.h文件:
main#ifndef __USART_H
#define __USART_H
#include “sys.h”
#include “stdio.h”
#define USART_REC_LEN 200 //接收最大字节数为200个字节
#define EN_USART1_RX 1 //使能-1/禁止-0
extern u8 USART_RX_BUF[USART_REC_LEN];
extern u16 USART_RX_STA; //接收状态标志
void uart_init(u32 bound);//端口配置函数
void uart_send_tx(u8 ch);
void uart_send_tx_s(u8 *pString);//发送字符串函数
#endif
main.c文件
#include “sys.h”
#include “delay.h”
#include “usart.h”
#include “led.h”
int main(void )
{
u8 t = 0;
u8 len; //保存接收数据的长度
u16 times=0;
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置中断分组,在sys.c文件中,如果不设置的的化默认分组为2
uart_init(9600); //串口初始化,内含中断的初始化
LED_Init();
while(1){
if(USART_RX_STA&0X8000){ //通过自定义寄存的最高位,判断是否成功收到数据
len = USART_RX_STA&0X3FFF; //获得此次接收数据的长度,USART_RX_STA低14位是记录数据长度的。
uart_send_tx_s(“发送成功,发送的数据为:rn”);
for(t = 0;t《len;t++){
USART_SendData(USART1,USART_RX_BUF[t]); //通过库函数发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//通过获取usart1状态寄存器的第6位确定数据有没有发送成功
}
printf(“rn”); //换行
USART_RX_STA=0; //发送完成,将状态归零,准备下一次接收数据
}
else{
times++;
if(times%100==0) //1秒发送一次消息,
uart_send_tx_s(“暂无数据发送!rn”);
if(times%30==0) //0.3秒进入一次,对times求余数
LED1 = ~LED1; //闪烁led表示系统正在运行
delay_ms(10);
}
}
}
/*************************************************************、
stm32串口程序在库函数开发指南的第179页
在uart.c文件中的特殊定义:
一个接收状态寄存器 USART_RX_STA(此寄存器其实就是一个全局
变量,由作者自行添加。由于它起到类似寄存器的功能,这里暂且称之为寄存器)实现对
串口数据的接收管理。USART_RX_BUF 的大小由 USART_REC_LEN 定义,也就是一次接
收的数据最大不能超过 USART_REC_LEN 个字节。
USART_RX_STA:
bit15, 接收完成标志
bit14, 接收到0x0d
bit13~0, 接收到的有效字节数目
*************************************************************/
调试过程

完整工程
完整工程可直接编译:
程序参考正点原子编写,此文章只作为本人笔记。如对你有帮助,那真是再好不过。今天就到这里goodbye!!
举报