1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > STM32F103ZET6+USART+串口通信

STM32F103ZET6+USART+串口通信

时间:2020-11-13 19:10:53

相关推荐

STM32F103ZET6+USART+串口通信

STM32F103ZET6+USART+串口通信

一、 通信概述

通信就是数据交换、信息交换。嵌入式系统中,微控制器与其他外围设备相互连接,系统各部件之间进行数字信号/数据的传输就是通信,无论是大型嵌入式系统还是小型嵌入式系统,都需要用到通信。

通信的方式有很多种,按数据传送方式可分为串行通信和并行通信;按通信数据同步方式可分为同步通信和异步通信;在串行通信中按数据传输方向及与时间的关系可分为单工通信、半双工通信和全双工通信。

二、 串行通信与并行通信

串行通信(Serial Transmission),是指通过一根数据线或少量数据线(少于8根)将数据一位一位地按顺序依次传送。

并行通信(Parallel Transmission),是指用多条数据线同时传送多位数据,通常以8位、16位、32位等数据位传送。并行通信一次可传输多个数据位的数据,并行通信传输数据量是串行传输的数倍,如早期的并行接口的硬盘、打印机,采用PCI(Peripheral Component Interconnect,外设部件互连标准)并行接口的显卡等。

并行传输的缺点:长距离传输成本较高;信号线之间的干扰大,传输速率很难达到很高;体积大,占用空间大,不利于设备的小型化。

三、 同步通信与异步通信

同步通信是连续串行传送数据的通信方式,要求收发双方的时钟必须保持严格的同步。特点:输速率较高

异步通信在发送的有效数据中增加一些用于同步的控制位,比如开始位和停止位等,数据以字符为单位组成数据帧进行传送,收发双方需约定数据的传输速率。特点:传输效率较低;通信设备实现简单、成本低。

四、单工、半双工、全双工通信

根据数据传输方向以及与时间的关系,串行通信可以分为单工、半双工和全双工三种通信方式。

波特率:每秒传输的二进制位数,单位为比特每秒(bit/s,bps),是衡量串行数据传输速度快慢的指标。

字符速率:每秒所传输的字符数:波特率=字符速率×每个字符包含的位数

五、 异步串行通信协议

异步串行通信标准的数据帧由起始位、数据位、校验位、停止位四部分组成。数据传输速率为50、75、100、150、300、600、1200、2400、4800、9600、19200和38400波特。

起始位:占一位,位于数据帧的开头,以逻辑“0”表示传输数据的开始。

数据位:要发送的数据,数据长度可以是5~8位。

校验位:占一位,用于检测数据是否有效。

停止位:一帧传送结束的标志,根据实际情况定,可以是1、1.5或2位。

空闲位:数据传输完毕,用“1”表示当前线路上没有数据传输。

UART(Universal Asynchronous Receiver Transmitter,通用异步收发传输器)是一个全双工通用异步串行收/发模块,主要用于打印程序调试信息、上位机和下位机的通信以及ISP程序下载等场合。

UART至少需要两根数据线用于通信双方进行数据双向同时传输,最简单的UART接口由TxD、RxD、GND共3根线组成。其中,TxD用于发送数据,RxD用于接收数据,GND为信号地线,通过交叉连接实现两个芯片间的串口通信。

六、STM32 USART编程模式

1、轮询模式

CPU不断地查询I/O设备是否准备就绪,如果准备就绪就发送,否则提示超时错误;会占用CPU的大量时间,效率低。

2、 中断方式

通过中断请求线,在I/O设备准备就绪时向CPU发出中断请求,CPU中止正在进行的工作转向处理I/O设备的中断事件;中断方式相比轮询方式效率较高。

3、DMA方式

直接存储器传送,不经过CPU直接在内存和外设之间进行批量数据交换,适用于高速大批量成组数据的传输;满足高速I/O设备的传输要求,有利于提高CPU的利用率。

USART串口应用编程步骤

1、声明GPIO和USART初始化结构体

USART_InitTypeDef USART_InitStructure;

2、串口所用的GPIO时钟使能,串口时钟使能

开启外设时钟RCC_APB2PeriphClockCmd()。例如:使能USART1、GPIOA的时钟,所用的函数为

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);

3、 设置I/O引脚功能为复用推挽输出、浮空输入

串口使用的是I/O的复用功能。USART1的发送引脚为PA9,需将PA9配置为复用推挽输出;USART1的输入引脚为PA10,需将PA10配置为浮空输入。

//USART1_TX,PA9,配置为复用推挽输出,并初始化PA9GPIO_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,PA10,配置为浮空输入,并初始化PA10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10

4、 设置波特率,设置数据格式:数据位、停止位、校验位

USART_InitStructure.USART_BaudRate = 115200;//串口波特率USART_InitStructure.USART_WordLength= USART_WordLength_8b; //设置数据位占8位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;//设置为收发模式

5、使用串口初始化函数USART_Init()初始化相应串口

USART_Init(USART1, &USART_InitStructure);//初始化串口1

6、利用串口使能函数USART_Cmd()使能相应串口

USART_Cmd(USART1, ENABLE);//使能串口

7、应用程序编写

若使用中断,则编写串口中断函数void USART1_IRQHandler(void)

接下来,设计通过串口1利用查询方式实现发送字符命令"Y"点亮LED灯,发送字符命令"N"熄灭LED灯。并且重定向printf()函数和scanf()函数,即重写fput()函数和fget()函数

采用查询方式进行数据通信

在之前的LED工程上,新建两个文件,一个是myusart.h文件,另一个是myusart.c文件

myusart.h文件的代码如下:

#ifndef __MYUSART_H#define __MYUSART_H#include "stm32f10x.h"#include <stdio.h>void USART_Init_Config(void);#endif

myusart.c文件的代码如下:

#include "myusart.h"void USART_Init_Config(void){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //开始USSART1和GPIOA的时钟USART_DeInit(USART1);//¸复位USART1//USART1_TX PA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择要使用的I/O引脚,此处选择PA9引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的输出速度为50MHzGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置引脚输出模式为复用推挽输出模式GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择要使用的I/O引脚,此处选择PA10引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置引脚输入模式为浮空输入模式GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1 配置USART_InitStructure.USART_BaudRate = 115200;//设置波特率为115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位占8位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_Init(USART1, &USART_InitStructure); //初始化串口1USART_Cmd(USART1, ENABLE); //使能串口1}//重定向printf函数int fputc(int ch, FILE *f){USART_SendData(USART1, (uint8_t) ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);return (ch);}//重定向scanf函数int fgetc(FILE *f){while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(USART1);}

main.c文件的代码如下:

#include "stm32f10x.h"#include "led.h"#include "myusart.h"int main(void){char ch;LED_Init();USART_Init_Config();while(1){ch = getchar();printf("接收到的指令º%c \n",ch);switch(ch){case 'N':GPIO_SetBits(GPIOB,GPIO_Pin_5);//熄灭LED灯printf("熄灭LED灯\n");break;case 'Y':GPIO_ResetBits(GPIOB,GPIO_Pin_5); //点亮LED灯printf("点亮LED灯\n");break;default:printf("请输入正确的指今,N熄灭灯,Y点亮灯!\n");break;}}}

运行效果

打开串口调试助手

接下来,设计通过串口1利用中断方式实现发送字符命令"1"点亮LED灯,发送字符命令"0"熄灭LED灯。并且重定向printf()函数和scanf()函数,即重写fput()函数和fget()函数

采用中断方式进行数据通信

myusart.h文件的代码如下:

#ifndef __MYUSART_H#define __MYUSART_H#include "stm32f10x.h"#include <stdio.h>void USART_Init_Config(void);#endif

myusart.c文件的代码如下:

#include "myusart.h"void USART_Init_Config(void){GPIO_InitTypeDef GPIO_InitStructure; //定义一个GPIO_InitTypeDef类型的结构体变量,用于配置GPIo引脚USART_InitTypeDef USART_InitStructure; //定义一个USART_InitTypeDer类型的结构体变量,用于配置串口NVIC_InitTypeDef NVIC_InitStructure; //定义一个NVIC_InitTypeDef类型的结构体变量,用于配置中断优先级RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //开始USART1和GPIOA的时钟USART_DeInit(USART1);//复位USART1//USART1_TX PA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择要使用的I/O引脚,此处选择PA9引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的输出速度为50MHzGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置引脚输出模式为复用推挽输出模式GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择要使用的I/O引脚,此处选择PA10引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置引脚输入模式为浮空输入模式GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1 配置USART_InitStructure.USART_BaudRate = 115200;//设置波特率为115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位占8位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_ClearFlag(USART1,USART_FLAG_TC); //清除发送完成标准USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //打开串口1的接收中断USART_ITConfig(USART1,USART_IT_TC,ENABLE); //开始串口1的发送中断USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_Cmd(USART1, ENABLE); //使能串口1// NVIC USART1 中断配置NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断优先级分组2NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //外部USART1中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级为0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级为0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道NVIC_Init(&NVIC_InitStructure); }//重定向printf函数int fputc(int ch, FILE *f){USART_SendData(USART1, (uint8_t) ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);return (ch);}//重定向scanf函数int fgetc(FILE *f){while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(USART1);}//中断处理函数void USART1_IRQHandler(void){uint8_t Rx_Data;if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){Rx_Data = (uint8_t)USART_ReceiveData(USART1);printf("输出的命令是 %c \n",Rx_Data);switch(Rx_Data){case '0':GPIO_SetBits(GPIOB,GPIO_Pin_5);printf("熄灭LED灯\n");break;case '1':GPIO_ResetBits(GPIOB,GPIO_Pin_5);printf("点亮LED灯 \n");break;default:printf("输入了错误的指令,请重新输入! \n");break;}}}

main.c文件的代码如下:

#include "stm32f10x.h"#include "led.h"#include "myusart.h"int main(void){LED_Init();USART_Init_Config();while(1){}}

运行效果

打开串口调试助手

接下来,设计通过串口1利用DMA方式实现循环发送字符。

采用DNA方式进行数据通信

myusart.h文件的代码如下:

#ifndef __MYUSART_H#define __MYUSART_H#include "stm32f10x.h"#include <stdio.h>#define SENDBUFF_SIZE 100void USARTx_Init_Config(void);void USARTx_DMA_Config(void);#endif

myusart.c文件的代码如下:

#include "myusart.h"uint8_t SendBuff[SENDBUFF_SIZE];void USARTx_Init_Config(void){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //开启USART1和GPIOA的时钟USART_DeInit(USART1);//¸复位USART1//USART1_TX PA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择要使用的I/O引脚,此处选择PA9引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚的输出速度为50MHzGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置引脚输出模式为复用推挽输出模式GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择要使用的I/O引脚,此处选择PA10引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置引脚输入模式为浮空输入模式GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1 USART_InitStructure.USART_BaudRate = 115200;//设置波特率为115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据位占8位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_Init(USART1, &USART_InitStructure); //初始化串口1USART_Cmd(USART1, ENABLE); //使能串口1USART_ClearFlag(USART1, USART_FLAG_TC|USART_FLAG_TXE|USART_FLAG_RXNE); //清除发送完成标志}void USARTx_DMA_Config(void){DMA_InitTypeDef DMA_InitStructure;/* 开启DNA时钟 */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/*设置DNA源:串口数据寄存器地址*/ DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&(USART1->DR));/*内存地址(要传输的变量指针)*/DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff;/*方向:从内存到外设*/DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;/*传输大小DMA_BufferSize=SENDBUFF_SIZE*/DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;/*外设地址不增*/ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /*内存地址自增*/DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;/*外设数据单位*/DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/*内存数据单位 8bit*/DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /*DMA模式:不断循环*/DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; /*优先级:中*/DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; /*禁止内存到内存的传输*/DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;/*配置DMA1的4通道*/ DMA_Init(DMA1_Channel4, &DMA_InitStructure);/*使能DMA*/DMA_Cmd (DMA1_Channel4,ENABLE);/* 配置DMA发送完成后产生中断 */DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); }//重定向printf函数int fputc(int ch, FILE *f){USART_SendData(USART1, (uint8_t) ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);return (ch);}//重定向scanf函数int fgetc(FILE *f){while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(USART1);}

main.c文件的代码如下:

#include "stm32f10x.h"#include "delay.h"#include "led.h"#include "myusart.h"extern uint8_t SendBuff[SENDBUFF_SIZE];int main(void){uint16_t i;delay_init();LED_Init(); //LED初始化USARTx_Init_Config(); //USART1初始化USARTx_DMA_Config(); //DMA初始化printf("使用DMA方式传输串口数据\n");/*输入要发送的数据,这里选用A作用A作为DMA传送的数据源*/for(i=0;i<SENDBUFF_SIZE;i++){SendBuff[i] = 'A';}/* USART1 向DMA发出TX请求 */USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); while(1){GPIO_SetBits(GPIOB,GPIO_Pin_5);delay_ms(1000);GPIO_ResetBits(GPIOB,GPIO_Pin_5);delay_ms(1000);}}

运行效果

打开串口调试助手

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。