版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
陕西科技大学实验报告PAGE第1页班级物联网131学号201306100129姓名周辉实验组别_____实验日期室温报告日期成绩__________报告内容:(目的和要求、原理、步骤、数据、计算、小结等)实验名称:串口通信实验实验目的掌握STM32串口通讯原理;掌握STM32串口编程掌握STM32单片机串口中断原理实验设备(1)硬件设备●超高频实验板一块;●J-LINK仿真器一套●PC机一台。●USB专用连接线一条(2)软件工具●STM32编译环境:KEIL4●串口测试软件:ComMonitor.exe实验原理本实验介绍STM32的串口基础,用STM32的串口来发送和接收数据。本实验将实现如下功能:STM32通过串口和上位机的对话,STM32在收到上位机发过来的字符串后,原原本本的返回给上位机。实验原理主要以下三个方面介绍:STM32串口简介串口作为MCU的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的MCU都会带有串口,STM32自然也不例外。STM32的串口资源相当丰富的,功能也相当强劲。本实验主要从库函数操作层面结合寄存器的描述,告诉大家如何设置串口,以达到最基本的通信功能。本实验将实现利用串口4不停的打印信息到电脑上,同时接收从串口发过来的数据,把发送过来的数据直接送回给电脑。超高频开发板自带1个USB串口。本实验介绍的是通过USB串口和电脑通信。STM32端口复用功能比较强大,对于复用功能的IO,首先要使能GPIO时钟,然后使能复用功能时钟,同时要把GPIO模式设置为复用功能对应的模式(这个可以查看手册《STM32中文参考手册V10》P110的表格“8.1.11外设的GPIO配置”)。这些准备工作做完之后,剩下的当然是串口参数的初始化设置,包括波特率,停止位等等参数。在设置完成只能接下来就是使能串口,这很容易理解。同时,如果我们开启了串口的中断,当然要初始化NVIC设置中断优先级别,最后编写中断服务函数。串口设置的一般步骤可以总结为如下几个步骤:1)串口时钟使能,GPIO时钟使能2)串口复位3)GPIO端口模式设置4)串口参数初始化5)开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)6)使能串口7)编写中断处理函数以下简单介绍下这几个与串口基本配置直接相关的几个固件库函数。这些函数和定义主要分布在stm32f10x_usart.h和stm32f10x_usart.c文件中。1.串口时钟使能。串口是挂载在APB2下面的外设,所以使能函数为:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);2.串口复位。当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。复位的是在函数USART_DeInit()中完成:voidUSART_DeInit(USART_TypeDef*USARTx);//串口复位比如要复位串口1,方法为:USART_DeInit(USART1);//复位串口13.串口参数初始化。串口初始化是通过USART_Init()函数实现的,voidUSART_Init(USART_TypeDef*USARTx,USART_InitTypeDef*USART_InitStruct);这个函数的的第一个入口参数是指定初始化的串口标号,这里选择USART1。第二个入口参数是一个USART_InitTypeDef类型的结构体指针,这个结构体指针的成员变量用来设置串口的一些参数。一般的实现格式为:USART_InitStructure.USART_BaudRate=bound;//一般设置为9600;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);//初始化串口从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,硬件数据流控制,模式(收,发)。可以根据需要设置这些参数。4.数据发送与接收。STM32的发送与接收是通过数据寄存器USART_DR来实现的,这是一个双寄存器,包含了TDR和RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,也是存在该寄存器内。STM32库函数操作USART_DR寄存器发送数据的函数是:voidUSART_SendData(USART_TypeDef*USARTx,uint16_tData);通过该函数向串口寄存器USART_DR写入一个数据。STM32库函数操作USART_DR寄存器读取串口接收到的数据的函数是:uint16_tUSART_ReceiveData(USART_TypeDef*USARTx);通过该函数可以读取串口接受到的数据。5.串口状态。串口的状态可以通过状态寄存器USART_SR读取。USART_SR的各位描述如图所示:图USART_SR寄存器各位描述这里关注一下两个位,第5、6位RXNE和TC。RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时候要做的就是尽快去读取USART_DR,通过读USART_DR可以将该位清零,也可以向该位写0,直接清除。TC(发送完成),当该位被置位的时候,表示USART_DR内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读USART_SR,写USART_DR。2)直接向该位写0。状态寄存器的其他位这里就不做过多讲解,大家需要可以查看中文参考手册。在固件库函数里面,读取串口状态的函数是:FlagStatusUSART_GetFlagStatus(USART_TypeDef*USARTx,uint16_tUSART_FLAG);这个函数的第二个入口参数非常关键,它是标示要查看串口的哪种状态,比如上面介绍的RXNE(读数据寄存器非空)以及TC(发送完成)。例如要判断读寄存器是否非空(RXNE),操作库函数的方法是:USART_GetFlagStatus(USART1,USART_FLAG_RXNE);要判断发送是否完成(TC),操作库函数的方法是:USART_GetFlagStatus(USART1,USART_FLAG_TC);这些标识号在MDK里面是通过宏定义定义的:#defineUSART_IT_PE((uint16_t)0x0028)#defineUSART_IT_TXE((uint16_t)0x0727)#defineUSART_IT_TC((uint16_t)0x0626)#defineUSART_IT_RXNE((uint16_t)0x0525)#defineUSART_IT_IDLE((uint16_t)0x0424)#defineUSART_IT_LBD((uint16_t)0x0846)#defineUSART_IT_CTS((uint16_t)0x096A)#defineUSART_IT_ERR((uint16_t)0x0060)#defineUSART_IT_ORE((uint16_t)0x0360)#defineUSART_IT_NE((uint16_t)0x0260)#defineUSART_IT_FE((uint16_t)0x0160)6.串口使能。串口使能是通过函数USART_Cmd()来实现的,使用方法是:USART_Cmd(USART1,ENABLE);//使能串口7.开启串口响应中断。有些时候当还需要开启串口中断,那么还需要使能串口中断,使能串口中断的函数是:voidUSART_ITConfig(USART_TypeDef*USARTx,uint16_tUSART_IT,FunctionalStateNewState)这个函数的第二个入口参数是标示使能串口的类型,也就是使能哪种中断,因为串口的中断类型有很多种。比如在接收到数据的时候(RXNE读数据寄存器非空),要产生中断,那么们开启中断的方法是:USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断,接收到数据中断在发送数据结束的时候(TC,发送完成)要产生中断,那么方法是:USART_ITConfig(USART1,USART_IT_TC,ENABLE);8.获取相应中断状态。当使能了某个中断的时候,当该中断发生了,就会设置状态寄存器中的某个标志位。经常在中断处理函数中,要判断该中断是哪种中断,使用的函数是:ITStatusUSART_GetITStatus(USART_TypeDef*USARTx,uint16_tUSART_IT)比如使能了串口发送完成中断,那么当中断发生了,便可以在中断处理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是:USART_GetITStatus(USART1,USART_IT_TC)返回值是SET,说明是串口发送完成中断发生。通过以上的介绍,就可以达到串口最基本的配置了,关于串口更详细的介绍,请参考《STM32参考手册》第516页至548页,通用同步异步收发器一章。硬件设计本实验需要用到的硬件资源有:指示灯D3串口4图4-7-1串口实验硬件电路图本实验使用串口4,接单片机PC10,PC11,通过USB转串口线直接和PC机相连,使用指示灯指示串口是否中断,D3连接PC0上.软件设计串口部分基本每个工程都要用到,因此放入系统SYSTEM文件夹下。大家只要根据需要改写相应的部分即可,这里对代码部分稍作介绍。打开串口实验工程,然后在SYSTEM组下双击usart.c,就可以看到该文件里面的代码,先介绍uart_init函数,该函数代码如下://初始化IO串口1//bound:波特率voiduart_init(u32bound){GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;NVIC_InitTypeDefNVIC_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_TXPA.9GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.9GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//USART1_RXPA.10GPIO_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);//初始化串口#ifEN_USART1_RX//如果使能了接收//⑤初始化NVICNVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ通道使能NVIC_Init(&NVIC_InitStructure);//中断优先级初始化//⑤开启中断USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断#endif//⑥使能串口USART_Cmd(USART1,ENABLE);//使能串口}从该代码可以看出,其初始化串口的过程,和前面介绍的一致。用标号①~⑥标示了顺序:①串口时钟使能,GPIO时钟使能②串口复位③GPIO端口模式设置④串口参数初始化⑤初始化NVIC并且开启中断⑥使能串口这里需要重申的是,对于复用功能下的GPIO模式怎么判定,这个需要查看《中文参考手册V10》P110的表格“8.1.11外设的GPIO配置”,查看手册得知,配置全双工的串口1,那么TX(PA9)管脚需要配置为推挽复用输出,RX(PA10)管脚配置为浮空输入或者带上拉输入。模式配置参考下面表格:表4-7-1串口GPIO模式配置表这里需要注意一点,因为使用到了串口的中断接收,必须在usart.h里面设置EN_USART1_RX为1(默认设置就是1的)。该函数才会配置中断使能,以及开启串口1的NVIC中断。这里把串口1中断放在组2,优先级设置为组2里面的最低。根据以上的步骤7,还要编写中断服务函数。串口1的中断服务函数voidUSART1_IRQHandler(void)函数是串口1的中断响应函数,当串口1发生了相应的中断后,就会跳到该函数执行。中断相应函数的名字是不能随便定义的,一般都遵循MDK定义的函数名。这些函数名字在启动文件startup_stm32f10x_hd.s文件中可以找到。函数体里面通过函数:if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)判断是否接受中断,如果是串口接受中断,则读取串口接受到的数据:Res=USART_ReceiveData(USART1);//(USART1->DR);//读取接收到的数据读到数据后接下来就对数据进行分析。设计了一个小小的接收协议:通过这个函数,配合一个数组USART_RX_BUF[],一个接收状态寄存器USART_RX_STA(此寄存器其实就是一个全局变量,由作者自行添加。由于它起到类似寄存器的功能,这里暂且称之为寄存器)实现对串口数据的接收管理。USART_RX_BUF的大小由USART_REC_LEN定义,也就是一次接收的数据最大不能超过USART_REC_LEN个字节。USART_RX_STA是一个接收状态寄存器其各的定义如表4-7-2所示:表4-7-2接收状态寄存器位定义表设计思路如下:当接收到从电脑发过来的数据,把接收到的数据保存在USART_RX_BUF中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的表示由2个字节组成:0X0D和0X0A)的第一个字节0X0D时,计数器将不再增加,等待0X0A的到来,而如果0X0A没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到0X0A,则标记USART_RX_STA的第15位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过USART_REC_LEN的时候,则会丢弃前面的数据,重新接收。中断相应函数代码如下:voidUSART1_IRQHandler(void)//串口1中断服务程序{u8Res;#ifdefOS_TICKS_PER_SEC//如果时钟节拍数定义了,说明要使用ucosII了.OSIntEnter();#endifif(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断(接收到的数据必须是0x0d0x0a结尾){Res=USART_ReceiveData(USART1);//(USART1->DR);//读取接收到的数据if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始elseUSART_RX_STA|=0x8000;//接收完成了}else//还没收到0X0D{if(Res==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;//接收数据错误,重新开始接收}}}}#ifdefOS_TICKS_PER_SEC//如果时钟节拍数定义了,说明要使用ucosII了.OSIntExit();#endif}EN_USART1_RX和USART_REC_LEN都是在usart.h文件里面定义的,当需要使用串口接收的时候,只要在usart.h里面设置EN_USART1_RX为1就可以了。不使用的时候,设置,EN_USART1_RX为0即可,这样可以省出部分sram和flash,默认是设置EN_USART1_RX为1,也就是开启串口接收的。OS_CRITICAL_METHOD,则是用来判断是否使用ucos,如果使用了ucos,则调用OSIntEnter和OSIntExit函数,如果没有使用ucos,则不调用这两个函数(这两个函数用于实现中断嵌套处理,这里先不理会。实验步骤1)打开Template工程模板文件工程Template.UV2,打开SYSTEM\usart.c,工程出厂默认是串口1,由于本实验使用串口4.因此需加入串口4的相关程序2)程序内部STM32RET6串口1、2、3使用没区别,串口4、5区别与前3个不同之处有两点串口1、2、3端口号使用USARTn,串口4、5端口号UARTn串口1、2、3是挂载在APB2下面的外设,串口4、5是挂载在APB1下面的外设。因此使用串口4只需将程序中的USART1替换为UART4,串口使能语句改写为:RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);其余保持不变。按如下步骤改写usart.c程序串口第31、32行改为while((UART4->SR&0X40)==0);UART4->DR=(u8)ch;程序第37行#ifEN_USART1_RX改为EN_USART4_RX将如下程序段复制到usart.c程序的第46行,保存voiduart4_init(u32bound){GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;NVIC_InitTypeDefNVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能USART4,GPIOC时钟USART_DeInit(UART4);//复位串口4//③GPIO端口模式设置GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//USART1_TXPC.10GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOC,&GPIO_InitStructure);//初始化GPIOC.10GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;//USART1_RXPC.11GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOC,&GPIO_InitStructure);//初始化GPIOC.11USART_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(UART4,&USART_InitStructure);//初始化串口#ifEN_USART4_RX//如果使能了接收NVIC_InitStructure.NVIC_IRQChannel=UART4_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ通道使能NVIC_Init(&NVIC_InitStructure);//中断优先级初始化USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);//开启中断#endifUSART_Cmd(UART4,ENABLE);//使能串口}voidUART4_IRQHandler(void)//串口1中断服务程序{u8Res;#ifdefOS_TICKS_PER_SEC//如果时钟节拍数定义了,说明要使用ucosII了.OSIntEnter();#endifif(USART_GetITStatus(UART4,USART_IT_RXNE)!=RESET)//接收中断(接收到的数据必须是0x0d0x0a结尾){Res=USART_ReceiveData(UART4);//(UART4->DR);//读取接收到的数据if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始elseUSART_RX_STA|=0x8000;//接收完成了}else//还没收到0X0D{if(Res==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;//接收数据错误,重新开始接收}}}}#ifdefOS_TICKS_PER_SEC//如果时钟节拍数定义了,说明要使用ucosII了.OSIntExit();#endif}打开SYSTEM\usart.h,以下两行程序插入第12行,保存#defineEN_USART4_RX 1 voiduart4_init(u32bound);5)打开main.c,在main.c里面编写如下代码:#include"led.h"#include"delay.h"#include"sys.h"#include"usart.h"intmain(void){u8t;u8len;u16times=0;delay_init();//延时函数初始化N
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论