精华内容
下载资源
问答
  • 《【经典】串口通信实验报告》由会员分享,可在线阅读,更多相关《【经典】串口通信实验报告(4页珍藏版)》请在人人文库网上搜索。1、VB串口通信实验1实验要求:设计一个串口通信程序,用于信息的接收和发送2实验目的...

    《【经典】串口通信实验报告》由会员分享,可在线阅读,更多相关《【经典】串口通信实验报告(4页珍藏版)》请在人人文库网上搜索。

    1、VB串口通信实验1实验要求:设计一个串口通信程序,用于信息的接收和发送2实验目的:2.1熟悉并掌握串口标准及原理;2.2实现PC机与PC机之间通过串口进行数据的收发;3.3熟悉VB语言编写程序的环境,用VB开发串口通信程序3实验步骤:3.1运行VB程序,出现“新建工程”对话框,选择“标准EXE”,单击“打开”命令按钮,进入VB工程集成开发环境;3.2 添加串口通信控件MSComm到工具箱中;3.3界面设计(1)添加两个文本框控件:Text1 和Text2,用于输入要发送的字符和显示要接收的字符;(2)添加两个标签控件:Label1和Label2,作为发送和接收字符区的标签;(3)添加一个按钮控。

    2、件:Command1执行发送字符命令;(4)添加一个MSComm控件。3.4属性设置窗体控件控 件 类 型主 要 属 性功 能Form(名称) = COMForm窗体控件BorderStyle = 3运行时窗体固定大小Caption = PC与PC串口通信窗体标题栏显示程序名称标签控件1Label(名称) = Label1标签控件Caption = 显示接收字符区:标签文本标签控件2Label(名称) = Label2标签控件Caption = 输入发送字符区:标签文本文本框控件1TextBox(名称) = Textsend文本框控件MultiLine = True允许多行显示ScrollBa。

    3、rs = 2-Vertical垂直滚动条可用文本框控件2TextBox(名称) = TextReceive文本框控件MultiLine = True允许多行显示ScrollBars = 2-Vertical垂直滚动条可用按钮控件CommandButton(名称) = Cmdsend按钮控件Caption = 发送字符 手动发送字符串口通信控件MSComm(名称) = MSComm1串口通信控件其他属性在程序中设置3.5程序代码设计Private Sub Form_Load()MSComm1.CommPort = 1 MSComm1.Settings = 9600,n,8,1 MSComm1.I。

    4、nputMode = 0 MSComm1.RThreshold = 1 MSComm1.PortOpen = True End SubPrivate Sub Cmdsend_Click()If Textsend.Text = Thenpp = MsgBox(发送的数据不能为空!, 16)Exit SubEnd IfMSComm1.Output = Trim(Textsend.Text)End SubPrivate Sub MSComm1_OnComm()Dim buf$Select Case MSComm1.CommEventCase comEvCD Case comEvCTS Case co。

    5、mEvDSR Case comEvReceive buf = Trim(MSComm1.Input) Case comEvSend End SelectTextReceive.Text = TextReceive.Text & bufEnd SubPrivate Sub Cmdquit_Click()Unload MeEnd SubPrivate Sub Form_Unload(Cancel As Integer)MSComm1.PortOpen = FalseEnd Sub3.5程序运行截图图1 主界面图2 发送信息图3 接收信息4.实验总结本次实验是利用VB实现计算机与计算机之间的串口通信,经过翻阅资料,对本实验所需要的知识都掌握好。通过实验,我也进一步发现了自己动手能力和自学能力都得到很多的进步,同时也对串口的发送与接收信息有了进一步的了解。

    展开全文
  • 实验四、串口通信实验

    千次阅读 多人点赞 2021-04-04 11:10:30
    实验四、串口通信实验 ​ 自律 学习 坚强 ,拒绝迷茫。 作者:行走的皮卡丘 时间:2021/4/4 喜欢就去追,这个红灯等不到,说不定下一个红灯等到了,嘻嘻!!!!!!! 文章目录实验四、串口通信实验一、 实验...

    实验四、串口通信实验

    ​ 自律 学习 坚强 ,拒绝迷茫。

    作者:行走的皮卡丘

    时间:2021/4/4

    喜欢就去追,这个红灯等不到,说不定下一个红灯等到了,嘻嘻!!!!!!!


    一、 实验目的

    • 1、 掌握STM32串口通信原理。

    • 2、 学习编程实现STM32的UART通信。

    二、 实验设备

    硬件:

    ​ PC机 一台

    ​ STM32开发板 一套

    软件:

    ​ MDK V4.0 一套

    ​ Windows 7 一套

    ​ 调试助手 一套

    三、 实验原理

    3.1、状态寄存器USART_SR及函数

    img

    第5、6位 RXNETC

    • RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,并且可以读出来了。

    • TC(发送完成),当该位被置位的时候,表示USART_DR内的数据已经被发送完成了。

    在固件库函数里面,读取串口状态的函数是:

    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx,  uint16_t  USART_FLAG )

    这个函数的第二个入口参数非常关键,它是标示我们要查看串口的哪种状态,比如上面讲解的RXNE(读数据寄存器非空)以及TC(发送完成)。

    例如:要判断读寄存器是否非空(RXNE),操作库函数的方法是:

    USART_GetFlagStatus(USART1,USART_FLAG_RXNE);
    

    要判断发送是否完成(TC),操作库函数的方法是:

    USART_GetFlagStatus(USART1,USART_FLAG_TC);
    

    3.2、USATR1 发送一个字节

    /****************************************************************
    
    USATR1 发送一个字节
    
    功能:发送一个字节的数据
    
    入口参数:发送到数据
    
    出口参数:无
    
    *****************************************************************/
    
    void Send_OneByte(uint8_t onebyte)
    
    {
    
      while(RESET == USART_GetFlagStatus(USART1, USART_FLAG_TC));//等待发送完毕USART_SendData(USART1, onebyte);	
    
    }
    

    3.3、接收一个字节的数据

    /****************************************************************
    
    功能:接收一个字节的数据
    
    入口参数:无
    
    出口参数:返回收到的数据
    
    *****************************************************************/
    
    uint8 rxdata;//存储收到的数据
    uint8 Receive_OneByte(void)
    {
    	if(USART_GetITStatus(USART1, USART_IT_RXNE)!= RESET)//串口收到数据
    	{
            rxdata = USART_ReceiveData(USART1);
        }
    	return rxdata;
    }
    

    3.4、串口编程为如下步骤:

    //1) 串口时钟使能, GPIO 时钟使能
    
    //配置时钟,由于使用串口是在复用IO口,需要打开串口时钟和相应的IO口时钟。
    
    
    //2) GPIO 端口模式设置
    
    //串口相应的IO口需要配置,输出口配置成复用推挽输出,输出速度根据需要配置,输入口配置为悬空输入。
        
    
    //3) 串口参数初始化,使能串口。(***\*串口调试助手 与之一致\**** )
    
     USART_InitTypeDef   USART_InitStructure;  
    
     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;  
    
     //收发模式 
     USART_Init(USART1, &USART_InitStructure );  //初始化串口1
    
     //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断。若无中断,该项不需要
    
     USART_Cmd(USART1, ENABLE);           //使能串口1 
    
    
    //4) 初始化 NVIC且开启中断(若开启中断才需要该步骤)
    
      NVIC_InitTypeDef   NVIC_InitStructure;  
    
      NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  
    
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;
    
      //抢占优先级0,级别可自己设定 ,下面的子优先级可自定
    
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;    //子优先级2  
    
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    
      //IRQ通道使能  
      NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器  
     
    
    //5) 编写中断处理函数 (有中断才需要该步骤)
    

    四、实验内容

    1、用STM32设计一个与计算机进行串口通讯的实验。STM32向PC发送 123ABC ,用串口调试助手 显示出来,用查询方式完成。

    2、用STM32设计一个与计算机进行串口通讯的实验。PC向STM32发送 456789 ,STM32接收后,将 每位数值+3 发送给PC,用 串口调试助手显示出来,用中断方式完成。

    3、用STM32设计一个与计算机进行串口通讯的实验,利用PC控制LED的亮灭。

    1)PC向STM32发送 A ,控制LED1,LED2,LED3同时亮灭,间隔时间0.5S,同时在 串口调试助手显示LED1,LED2,LED3同时亮灭”。

    2)PC向STM32发送 B ,控制LED1,LED2,LED3正向流水亮灭,间隔时间1S,同时在串口调试助手显示LED1,LED2,LED3正向流水亮灭”。

    3)PC向STM32发送 C ,控制LED1,LED2,LED3反向流水亮灭,间隔时间2S,同时在 串口调试助手显示LED1,LED2,LED3反向流水亮灭”。

    4、利用定时器结合串口实现 电子时钟的功能。功能如下:

    1)定时器完成 1S 的定时。

    2)串口调试助手*上显示时间,格式参考如下 12:34:56 ,每秒递增。串口调试助手每2秒刷新一次。

    ③在LCD上显示时间,格式参考如下 12:34:56 ,每秒递增。例程可参考 FSMC-液晶显示-英文的配套例程。

    4.1、用STM32设计一个与计算机进行串口通讯的实验。STM32向PC发送 123ABC,用串口调试助手显示出来,查询方式完成。(代码:实验4-1)

    img

    usart.c函数

    #include "sys.h"
    #include "usart.h"	  
     
    #pragma import(__use_no_semihosting)             
    //标准库需要的支持函数                 
    struct __FILE 
    { 
    	int handle; 
    
    }; 
    
    FILE __stdout;       
    //定义_sys_exit()以避免使用半主机模式    
    void _sys_exit(int x) 
    { 
    	x = x; 
    } 
    //重定义fputc函数 
    int fputc(int ch, FILE *f)
    {      
    	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
        USART1->DR = (u8) ch;      
    	return ch;
    }
    
    //串口1中断服务程序
    //注意,读取USARTx->SR能避免莫名其妙的错误   	
    u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
    //接收状态
    //bit15,	接收完成标志
    //bit14,	接收到0x0d
    //bit13~0,	接收到的有效字节数目
    u16 USART_RX_STA=0;       //接收状态标记	  
      
    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, ENABLE);	//使能USART1,GPIOA时钟
      
    	//USART1_TX   GPIOA.9
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
      GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
       
      //USART1_RX	  GPIOA.10初始化
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
      GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
    
      //Usart1 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);	//根据指定的参数初始化VIC寄存器
      
       //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);                    //使能串口1 
    
    }
    
    void USART1_IRQHandler(void)                	//串口1中断服务程序
    	{
    	u8 Res;
    	if(USART_GetITStatus(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;	//接收完成了 
    				}
    			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;//接收数据错误,重新开始接收	  
    					}		 
    				}
    			}   		 
         } 
    
    } 
    

    usart.h函数

    #ifndef __USART_H
    #define __USART_H
    #include "stdio.h"	
    #include "sys.h" 
    
    #define USART_REC_LEN  			200  	//定义最大接收字节数 200
    #define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
    	  	
    extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
    extern u16 USART_RX_STA;         		//接收状态标记	
    //如果想串口中断接收,请不要注释以下宏定义
    void uart_init(u32 bound);
    
    #endif
    

    main函数

    #include "delay.h"
    #include "sys.h"
    #include "usart.h"
    
    /**************************************************
    * Function       main
    * @author        行走的皮卡丘
    * @date          2021/4/4
    * @brief        
    * @param[in]    
    * @param[out]    void
    * @retval        void
    * @par History   无
    * TXD PA.9
    * RXD PA.10
    *************************************************/
     int main(void)
     {		
     	u16 t;  
    	u8 data[10]="123ABC";
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为115200
     	while(1)
    	{	   
    		printf("\r\nSTM32发送的消息为:  ");
    		for(t=0;t<sizeof(data);t++)
    		{
    			USART_SendData(USART1, data[t]);//向串口1发送数据
    			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
    		}
    		printf("\r\n");//插入换行
    		delay_ms(1000);
    	}	 
     }
    

    4.2、用STM32设计一个与计算机进行串口通讯的实验。PC向STM32发送 456789 ,STM32接收后,将 每位数值+3 发送给PC,用 串口调试助手 显示出来,用中断方式完成。(代码:实验4-2)

    img

    main函数

    #include "sys.h"
    #include "usart.h"
    /**************************************************
    * Function       main
    * @author        行走的皮卡丘
    * @date          2021/4/4
    * @brief        
    * @param[in]    
    * @param[out]    void
    * @retval        void
    * @par History   无
    * TXD PA.9
    * RXD PA.10
    *************************************************/
    
     int main(void)
     {		
    	char String[]="0123456789ABCDEFG";
     	u8  i;	 
      u8 data;
    	u16 len;
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为115200
     	while(1)
    	{
    		if(USART_RX_STA&0x8000)
    		{			
    			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
    			USART_RX_BUF[len] = 0;
    			printf("\r\n PC发送的消息为:%s\r\n",USART_RX_BUF);
    			printf(" STM32发送的消息为:");
    			for(i = 0;i < len;i++)
    			{
    				data=String[ USART_RX_BUF[i] - 48 + 3 ];
    				printf("%c",data);
    			}
    			printf("\r\n");//插入换行
    			USART_RX_STA=0;
    		}
    	}	 
     }
    

    4.2.3、用STM32设计一个与计算机进行串口通讯的实验,利用PC控制LED的亮灭。(代码:实验4-3)

    1)PC向STM32发送 A ,控制LED1,LED2,LED3同时亮灭,间隔时间0.5S,同时在 串口调试助手显示LED1,LED2,LED3同时亮灭”。

    2)PC向STM32发送 B ,控制LED1,LED2,LED3正向流水亮灭,间隔时间1S,同时在 串口调试助手显示LED1,LED2,LED3正向流水亮灭”。

    3)PC向STM32发送 C ,控制LED1,LED2,LED3反向流水亮灭,间隔时间2S,同时在 串口调试助手显示LED1,LED2,LED3反向流水亮灭”。

    img

    #include "delay.h"
    #include "sys.h"
    #include "usart.h"
    
    
    /**************************************************
    * Function       main
    * @author        行走的皮卡丘
    * @date          2021/4/4
    * @brief        
    * @param[in]    
    * @param[out]    void
    * @retval        void
    * @par History   无
    * TXD PA.9
    * RXD PA.10
    *************************************************/
    
    #define LED1 PBout(0)
    #define LED2 PCout(4)
    #define LED3 PCout(3)
    
    void LED_Init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStr;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);//   
    	
    	
    	GPIO_InitStr.GPIO_Mode=GPIO_Mode_Out_PP;//推挽
    	GPIO_InitStr.GPIO_Pin=GPIO_Pin_0;
    	GPIO_InitStr.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStr);  // PB0   LED1
    	
    	GPIO_InitStr.GPIO_Pin=GPIO_Pin_4;
    	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC4   LED2
    	GPIO_InitStr.GPIO_Pin=GPIO_Pin_3;
    	GPIO_Init(GPIOC,&GPIO_InitStr);  // PC3   LED3
    
    	GPIO_SetBits(GPIOB,GPIO_Pin_0); 
    	GPIO_SetBits(GPIOC,GPIO_Pin_4); 
    	GPIO_SetBits(GPIOC,GPIO_Pin_3); 
    }
    
    
     int main(void)
     {		
     	u16 i=0;  
    	u16 len;	
    	u16 data;
    	 
    	LED_Init();			     //LED端口初始化
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为115200
     	
     	while(1)
    	{
    	    if(USART_RX_STA&0x8000)  //接收数据
    			{
    					len = USART_RX_STA&0x3f; 
    					for(i = 0;i < len; i++)
    					{
    						data = USART_RX_BUF[i];
    						while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);	
    					}
    					USART_RX_STA = 0;	
    					
    					if(data == 'A')
    					{
    							data = 0;
    							printf("LED1,LED2,LED3同时亮灭\r\n");
    							LED1=1; LED2=1; LED3=1;
    							while(USART_RX_STA==0)
    							{
    								LED1=~LED1; LED2=~LED2; LED3=~LED3;
    								delay_100ms(5);
    							}				
    					}
    					
    					if(data == 'B')
    					{
    							data = 0;
    							printf("LED1,LED2,LED3正向流水亮灭\r\n");
    							while(USART_RX_STA==0)
    							{
    								LED1=1; LED2=1; LED3=0;
    								delay_100ms(10);
    								LED1=1; LED2=0; LED3=1;
    								delay_100ms(10);				
    								LED1=0; LED2=1; LED3=1;
    								delay_100ms(10);				
    							}				
    					}
    					
    					if(data == 'C')
    					{
    							data = 0;
    							printf("LED1,LED2,LED3反向流水亮灭\r\n");
    							LED1=1; LED2=1; LED3=1;
    							while(USART_RX_STA==0)
    							{
    								LED1=0; LED2=1; LED3=1;
    								delay_100ms(20);
    								LED1=1; LED2=0; LED3=1;
    								delay_100ms(20);				
    								LED1=1; LED2=1; LED3=0;
    								delay_100ms(20);
    							}				
    					}				
    			}			
    	}	 
    }
    

    4.4、利用定时器结合串口实现 电子时钟的功能。(代码:实验4-4)

    • 定时器完成 1S 的定时。

    • 形参设置为arr=9999,psc=7199即可

    img

    • 串口调试助手上显示时间,格式参考如下 12:34:56 ,每秒递增。串口调试助手每2秒刷新一次。

    • 主函数中的死循环,其中flay在定时器2的中断中累加,即一秒以1累加。

    img

    • 在LCD上显示时间,格式参考如下 12:34:56,每秒递增。例程可参考FSMC-液晶显示-英文的配套例程。

    img

    main函数

    #include "led.h"
    #include "delay.h"
    #include "sys.h"
    #include "usart.h"
    #include "timer.h"
    #include "lcd.h" 
    
    /**************************************************
    * Function       main
    * @author        行走的皮卡丘
    * @date          2021/4/4
    * @brief        
    * @param[in]    
    * @param[out]    void
    * @retval        void
    * @par History   无
    * TXD PA.9
    * RXD PA.10
    *************************************************/
    
    
    
     int main(void)
     {		
    	ILI9341_Init();
    	ILI9341_GramScan( 6 );  //设置默认扫描方向,其中 6 模式为大部分液晶例程的默认显示方向  
    	LCD_SetColors(GBLUE,BLACK); 		//设置颜色
    	ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);
    	LCD_SetFont(&Font16x24);
    	LCD_SetTextColor(GREEN);   //设置文本颜色
    	 
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为115200
     	LED_Init();			     //LED端口初始化
    	TIM2_Int_Init(9999,7199); //一秒一次中断  72 000 000 /7200=10000  10000/10000=1hz 1/1hz=1s
    	 
     	while(1)
    	{
    		if( flay==2 )
    		{
    			flay = 0;
    		  printf("%s\r\n",TimeStr);
    		}
    		
    	}	 
     }
    

    四、实验总结

    加油!!!行走的皮卡丘!!!!

    实验四代码下载链接

    展开全文
  • USART 串口通信实验 我们知道STM32F1 内部含有非常多的通信接口,我们就来学习下USART 串口通信。要实现的功能是:STM32F1 通过USART1 实现与PC 机对话,STM32F1 的USART1 收到PC 机发来的数据后原封不动的返回给PC ...

    USART 串口通信实验

    我们知道STM32F1 内部含有非常多的通信接口,我们就来学习下USART 串口通信。要实现的功能是:STM32F1 通过USART1 实现与PC 机对话,STM32F1 的USART1 收到PC 机发来的数据后原封不动的返回给PC 机显示。分为如下几部分内容:

    1. 通信的基本概念
    2. STM32F4 的USART 介绍
    3. USART 串口通信配置步骤
    4. 硬件设计
    5. 软件设计

    1 . 通信的基本概念

    我们知道STM32F1 芯片内含有非常多的通信接口,学习这些通信接口前,我们很有必要了解下通信的基本概念。通信的方式可以分为多种:

    • 按照数据传送方式可分为串行通信和并行通信
    • 按照通信的数据同步方式,可分为异同通信和同步通信
    • 按照数据的传输方向又可分为单工、半双工和全双工通信
      下面我们就来简单介绍这几种通信方式:

    串行通信与并行通信
    (1)串行通信
    串行通信是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。其只需要少数几条线就可以在系统间交换信息,特别适用于计算机与计算机、计算机与外设之间的远距离通信。如图所示:
    在这里插入图片描述
    串行通信的特点:传输线少,长距离传送时成本低,且可以利用电话网等现成的设备,但数据的传送控制比并行通信复杂。

    (2)并行通信
    并行通信通常是将数据字节的各位用多条数据线同时进行传送,通常是8位、16 位、32 位等数据一起传输。如图所示:
    在这里插入图片描述
    并行通信的特点:控制简单、传输速度快;由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难,抗干扰能力差。

    异步通信与同步通信
    (1)异步通信
    异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。异步通信数据格式如图所示:
    在这里插入图片描述
    在这里插入图片描述

    异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加2~3 位用于起止位,各帧之间还有间隔,因此传输效率不高。

    (2)同步通信
    同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。发送方对接收方的同步可以通过两种方法实现。同步通信数据格式如图所示:
    在这里插入图片描述
    单工、半双工与全双工通信
    (1)单工通信
    单工是指数据传输仅能沿一个方向,不能实现反向传输。如下图所示:
    在这里插入图片描述

    (2)半双工通信
    半双工是指数据传输可以沿两个方向,但需要分时进行。如下图所示:
    在这里插入图片描述

    (3)全双工通信
    全双工是指数据可以同时进行双向传输。如下图所示:
    在这里插入图片描述

    通信速率
    衡量通信性能的一个非常重要的参数就是通信速率,通常以**比特率(Bitrate)**来表示。比特率是每秒钟传输二进制代码的位数,单位是:位/秒(bps)。如每秒钟传送240 个字符,而每个字符格式包含10 位(1 个起始位、1 个停止位、8个数据位),这时的比特率为:
    10 位×240 个/秒= 2400 bps
    在后面会遇到一个“波特率”的概念,它表示每秒钟传输了多少个码元。而码元是通信信号调制的概念,通信中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。如常见的通信传输中,用0V 表示数字0, 5V 表示数字1,那么一个码元可以表示两种状态0 和1,所以一个码元等于一个二进制比特位,此时波特率的大小与比特率一致;如果在通信传输中,有0V、2V、
    4V 以及6V 分别表示二进制数00、01、10、11,那么每个码元可以表示四种状态,即两个二进制比特位,所以码元数是二进制比特位数的一半,这个时候的波特率为比特率的一半。由于很多常见的通信中一个码元都是表示两种状态,所以我们常常直接以波特率来表示比特率。

    STM32F1 的USART 介绍

    串口通信简介
    串口通信(Serial Communication),是指外设和计算机间通过数据信号线、地线等按位进行传输数据的一种通信方式,属于串行通信方式。串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。
    (1)接口标准
    串口通信的接口标准有很多,有RS-232C、RS-232、RS-422A、RS-485 等。常用的就是RS-232 和RS-485。RS-232 其实是RS-232C 的改进,原理是一样的。这里我们就以RS-232C 接口进行讲解。RS-232C 是EIA(美国电子工业协会)1969 年修订RS-232C 标准。RS-232C定义了数据终端设备(DTE)与数据通信设备(DCE)之间的物理接口标准。RS-232C 接口规定使用25 针连接器,简称DB25,连接器的尺寸及每个插针的排列位置都有明确的定义,如图所示:
    在这里插入图片描述
    RS-232C 还有一种9 针的非标准连接器接口,简称DB9。串口通信使用的大多都是DB9 接口。DB25 和DB9 接头有公头和母头之分,其中带针状的接头是公头,而带孔状的接头是母头。9 针串口线的外观图如图所示:
    在这里插入图片描述
    中可以看到公头和母头的管脚定义顺序是不一样,这一点需要特别注意。这些管脚都有什么作用呢?9 针串口和25 针串口常用管脚的功能说明如图所示:
    在这里插入图片描述
    在串口通信中,通常我们只使用2、3、5 三个管脚,即TXD、RXD、SGND,其他管脚功能大家看不明白也没关系。RS-232C 对逻辑电平也做了规定

    在TXD 和RXD 数据线上:
    1.逻辑1 为-3~-15V 的电压
    2.逻辑0 为3~15V 的电压
    在RTS、CTS、DSR、DTR 和DCD 等控制线上:
    1.信号有效(ON 状态)为3~15V 的电压
    2.信号无效(OFF 状态)为-3~-15V 的电压

    由此可见,RS-232C 是用正负电压来表示逻辑状态与晶体管-晶体管逻辑集成电路(TTL)以高低电平表示逻辑状态的规定正好相反而我们STM32 芯片使用的就是TTL 电平,所以要实现STM32 与计算机的串口通信,需要进行TTL与RS-232C电平转换,通常使用的电平转换芯片是MAX3232。在串口通信中通常PC机的DB9 为公头,单片机上使用的串口DB9 为母头,通过一根直通串口线进行相连。串口线(COM)母头连接计算机DB9 的公头,串口线公头连接单片机上使用的DB9 母头,这样就是将2、3、5 管脚直接相连。如果你要实现两台计算机串口通信,那么就需要一根交叉串口线,将2 对3、3 对2、5 对5 连接,交叉串口线一般两头都是母头。串口通信中还需要注意的是,串口数据收发线要交叉连接,计算机的TXD要对应单片机的RXD,计算机的RXD 要对应单片机的TXD,并且共GND,如下图:有的朋友就会问了,在计算机与单片机进行串口通信时,使用的不是直通线吗,这时候怎么让TXD 与RXD 交叉连接?前面我们说了单片机处理的是TTL 电平,需要使用RS232 电平转换芯片,将RS232 电平转换芯片串行数据输出管脚交叉连接在DB9 母头上即可。

    (2)通信协议
    RS232 的通信协议比较简单,通常遵循96-N-8-1 格式。“96”表示的是通信波特率为9600。串口通信中通常使用的是异步串口通信,即没有时钟线,所以两个设备要通信,必须要保持一致的波特率,当然,波特率常用值还有4800、115200 等。“N”表示的是无校验位,由于串口通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无校验(noparity)。“8”表示的是数据位数为8 位,其数据格式在前面介绍异步通信中已讲过。当然数据位数还可以为5、6、7 位长度。“1”表示的是1 位停止位,串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑1 的数据位表示,只要双方约定一致即可。了解了串口通信的标准,我们就来看下STM32F1 芯片的串口USART。

    USART 简介
    USART 即通用同步异步收发器,它能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。UART 即通用异步收发器,它是在USART 基础上裁剪掉了同步通信功能,同步和异步主要看其时钟是否需要对外提供,这个前面也介绍了, 我们平时使用的串口通信基本上都是UART。STM32F103ZET6 芯片含有3 个USART,2 个UART 外设,它们都具有串口通信功能。USART 支持同步单向通信和半双工单线通信;还支持LIN(域互连网络)、智能卡协议与IrDA(红外线数据协会) SIR ENDEC 规范,以及调制解调器操作(CTS/RTS)。而且,它还支持多处理器通信和DMA 功能,使用DMA 可实现高速数据通信。USART 通过小数波特率发生器提供了多种波特率。USART 在STM32 中应用最多的是printf 输出调试信息,当我们需要了解程序内的一些变量数据信息时,可以通过printf 输出函数将这些信息打印到串口助手上显示,这样一来就给我们调试程序带来了极大的方便。

    USART 结构框图
    其实USART 能够有这么多功能,取决于它的内部结构。其内部结构框图如图:

    在这里插入图片描述
    我们把图21.2.4 分为几个模块进行介绍:
    (1)标号1:功能引脚

    • TX:发送数据输出引脚。
    • RX:接收数据输入引脚。
    • SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚
    • nRTS:请求以发送(Request To Send),n 表示低电平有效。如果使能RTS 流控制,当USART接收器准备好接收新数据时就会将nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。
    • nCTS:清除以发送(Clear To Send),n 表示低电平有效。如果使能CTS 流控制,发送器在发送下一帧数据之前会检测nCTS引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
    • SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。前面我们说了,STM32F103ZET6 芯片具有5个串口外设,其对应的管脚可在芯片数据手册上查找到,也可以直接查看我们开发板原理图,我们已经将芯片所有的IO口功能都标注在管脚上了。
      USART1 挂接在APB2 总线上,其他的挂接在APB1 总线,由于UART4 和UART5只有异步传输功能,所以没有SCLK、nCTS 和nRTS脚,如下:
      在这里插入图片描述
      (2)标号2:数据寄存器
      USART 数据寄存器(USART_DR)只有低9 位有效,并且第9 位数据是否有效要取决于USART 控制寄存器1(USART_CR1)的M 位设置,当M 位为0 时表示8 位数据字长,当M 位为1 表示9 位数据字长,我们一般使用8 位数据字长。USART_DR 包含了已发送的数据或者接收到的数据。USART_DR 实际是包含了两个寄存器,一个专门用于发送的可写TDR,一个专门用于接收的可读RDR。当进行发送操作时,往USART_DR 写入数据会自动存储在TDR 内;当进行读取操作时,向USART_DR 读取数据会自动提取RDR 数据。TDR 和RDR 都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到RDR。USART 支持DMA 传输,可以实现高速数据传输,具体DMA 使用在后面会更新介绍。
      (3)标号3:控制器
      USART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用USART 之前需要向USART_CR1 寄存器的UE 位置1 使能USART。发送或者接收数据字长可选8 位或9 位,由USART_CR1 的M 位控制。
      1.发送器
      发送器可发送8 位或9 位的数据,具体取决于M 位的状态。发送使能位(TE) 置1 时,发送移位寄存器中的数据在TX 引脚输出,如果是同步通信模式,相应的时钟脉冲在SCLK 引脚输出。
      2.接收器
      如果将USART_CR1 寄存器的RE 位置1,使能USART 接收,使得接收器在RX 线开始搜索起始位。在确定到起始位后就根据RX 线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器数据移到RDR 内,并把USART_SR 寄存器RXNE 位置1,同时如果USART_CR2 寄存器的RXNEIE 置1的话可以产生中断。
      3.中断控制
      USART 有多个中断请求事件,如下:
      在这里插入图片描述
      USART 中断事件被连接到相同的中断向量,如下:
      在这里插入图片描述
      (4)标号4:小数波特率生成
      波特率的概念在前面介绍比特率的时候已经提过,常用的串口通信中都把波特率当作比特率。波特率越大,传输速度就越快。接收器和发送器( Rx 和Tx)的波特率均设置为相同值。波特率计算公式如下:
      在这里插入图片描述
      其中,fCK 为USART 时钟频率,USARTDIV 是一个存放在波特率寄存器(USART_BRR)的一个无符号定点数。其中DIV_Mantissa[11:0]位定义USARTDIV的整数部分,DIV_Fraction[3:0]位定义USARTDIV 的小数部分。串口通信中常用的波特率为4800、9600、115200 等。

    USART 串口通信配置步骤

    在上面的介绍中,可能有的朋友很不理解,不过没有关系,下面我们讲解如何使用库函数对USART 进行配置。这个也是在编写程序中必须要了解的。具体步骤如下:(USART 相关库函数在stm32f10x_usart.c 和stm32f10x_usart.h 文件中)

    (1)使能串口时钟及GPIO 端口时钟

    前面说过STM32F103ZET6 芯片具有5 个串口,对应不同的引脚,串口1 挂接在APB2 总线上,串口2-串口5 挂接在APB1 总线上,根据自己所用串口使能总线时钟和端口时钟。例如使用USART1,其挂接在APB2 总线上,并且USART1 对应STM32F103ZET6 芯片管脚的PA9 和PA10,因此使能时钟函数如下:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);// 使能USART1 时钟
    

    (2)GPIO 端口模式设置,设置串口对应的引脚为复用功能

    因为使用引脚的串口功能,所以在配置GPIO 时要将设置为复用功能,这里把串口的Tx 引脚配置为复用推挽输出, Rx 引脚为浮空输入,数据完全由外部输入决定。如下:

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX // 串口输入PA10
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; // 模拟输入
    GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
    

    (3)初始化串口参数,包含波特率、字长、奇偶校验等参数要使用串口功能,必须对串口通信相关参数初始化,其库函数如下:

    void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef*USART_InitStruct);
    

    想必不用说,大家也知道第一个参数是什么意思,它是用来选择串口。第二个参数是一个结构体指针变量,结构体类型是 USART_InitTypeDef,其内包含了串口初始化的成员变量。下面我们就来看下这个结构体:

    typedef struct
    {
    uint32_t USART_BaudRate; //波特率
    uint16_t USART_WordLength; //字长
    uint16_t USART_StopBits; //停止位
    uint16_t USART_Parity; //校验位
    uint16_t USART_Mode; //USART 模式
    uint16_t USART_HardwareFlowControl; //硬件流控制
    } USART_InitTypeDef;
    

    下面就来简单介绍下每个成员变量的功能:
    USART_BaudRate: 波特率设置。常用的波特率为4800、9600、115200 。标准库函数会根据设定值计算得到USARTDIV 值, 并设置USART_BRR寄存器值。
    USART_WordLength: 数据帧字长。可以选择为8 位或者9 位,通过USART_CR1寄存器的M 位的值决定。如果没有使能奇偶校验控制,一般使用8 数据位;如果使能了奇偶校验则一般设置为9 数据位。
    USART_StopBits: 停止位设置。可选0.5 个、1 个、1.5 个和2 个停止位,它设定USART_CR2 寄存器的STOP[1:0]位的值,一般我们选择1 个停止位。
    USART_Parity: 奇偶校验控制选择。可选USART_Parity_No( 无校验) 、USART_Parity_Even( 偶校验) 以及USART_Parity_Odd( 奇校验) ,它设定USART_CR1 寄存器的PCE 位和PS 位的值。
    USART_Mode: USART 模式选择。可以为USART_Mode_Rx 和USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定USART_CR1 寄存器的RE 位和TE 位。**USART_HardwareFlowControl:**硬件流控制选择。只有在硬件流控制模式才有效, 可以选择无硬件流USART_HardwareFlowControl_None 、RTS 控制USART_HardwareFlowControl_RTS、CTS 控制USART_HardwareFlowControl_CTS、RTS 和CTS 控制USART_HardwareFlowControl_RTS_CTS。

    了解结构体成员功能后,就可以进行配置,例如我们配置USART1,如下:

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 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); //初始化串口1
    

    (5)使能串口

    配置好串口后,我们还需要使能它,使能串口库函数如下:

    void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
    

    例如我们要使能USART1,如下:

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

    (6)设置串口中断类型并使能

    对串口中断类型和使能设置的函数如下:

    void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,FunctionalState NewState);
    

    第一个参数用来选择串口,第二个参数用来选择串口中断类型,第三个参数用来使能或者失能对应中断。由于串口中断类型比较多,所以使用哪种中断,我们就需要对它进行配置。比如在接收到数据的时候( RXNE 读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是:

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启接收中断
    

    又比如我们发送完数据时,要产生中断,可以配置如下:

    USART_ITConfig(USART1,USART_IT_TC, ENABLE);
    

    对应的串口中断类型可在stm32f10x_usart.h 中查找到,如下:

    #define USART_IT_PE	 	((uint16_t)0x0028)
    #define USART_IT_TXE	 	((uint16_t)0x0727)
    #define USART_IT_TC		 ((uint16_t)0x0626)
    #define USART_IT_RXNE	 ((uint16_t)0x0525)
    #define USART_IT_IDLE	 ((uint16_t)0x0424)
    #define USART_IT_LBD 	((uint16_t)0x0846)
    #define USART_IT_CTS 	((uint16_t)0x096A)
    #define USART_IT_ERR	 ((uint16_t)0x0060)
    #define USART_IT_ORE	 ((uint16_t)0x0360)
    #define USART_IT_NE		 ((uint16_t)0x0260)
    #define USART_IT_FE		 ((uint16_t)0x0160)
    

    (7)设置串口中断优先级,使能串口中断通道

    在上一步我们已经使能了串口的接收中断,只要使用到中断,就必需对NVIC初始化,NVIC 初始化库函数是NVIC_Init(),这个在前面讲解STM32 中断时就已经介绍过,不清楚的可以回过头看下。

    (8)编写串口中断服务函数

    最后我们还需要编写一个串口中断服务函数,通过中断函数处理串口产生的相关中断。串口中断服务函数名在STM32F1 启动文件内就有,USART1 中断函数名如下:

    USART1_IRQHandler
    

    因为串口的中断类型有很多,所以进入中断后,我们需要在中断服务函数开头处通过状态寄存器的值判断此次中断是哪种类型,然后做出相应的控制。库函数中用来读取串口中断状态标志位的函数如下:

    ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_tUSART_IT);
    

    此函数功能是判断USARTx 的中断类型USART_IT 是否产生中断,例如我们要判断USART1 的接收中断是否产生,可以调用此函数:

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
    ...//执行USART1 接收中断内控制
    }
    

    如果产生接收中断,那么调用USART_GetITStatus 函数后返回值为1,就会进入到if 函数内执行中断控制功能程序。否则就不会进入中断处理程序。在编写串口中断服务函数时,最后通常会调用一个清除中断标志位的函数,如下:

    void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
    

    第二个参数为状态标志选项,可选参数可在stm32f10x_usart.h 中查找到,如下:

    #define USART_FLAG_CTS
    #define USART_FLAG_LBD
    #define USART_FLAG_TXE
    #define USART_FLAG_TC
    #define USART_FLAG_RXNE
    #define USART_FLAG_IDLE
    #define USART_FLAG_ORE
    #define USART_FLAG_NE
    #define USART_FLAG_FE
    #define USART_FLAG_PE
    

    比如本实验中判断串口进入接收中断后,我们就会把串口接收寄存器内数据读取出来,然后再通过串口发送至上位机,等待发送完成后我们就会清除发送完成标志位
    USART_FLAG_TC。代码如下:

    void USART1_IRQHandler(void) //串口1 中断服务程序
    {
    	u8 r;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
    		{
    		r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
    		USART_SendData(USART1,r);
    		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
    		}
    	USART_ClearFlag(USART1,USART_FLAG_TC);
    }
    

    串口接收函数是:

    uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
    

    串口发送函数是:

    void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
    

    库函数中还有一个函数用来读取串口状态标志位:

    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_tUSART_FLAG);
    

    USART_GetITStatus 与USART_GetFlagStatus 功能类似, 区别就是USART_GetITStatus 函数会先判断是否使能串口中断,使能后才读取状态标志,而USART_GetFlagStatus 函数直接读取状态标志。将以上几步全部配置好后,我们就可以正常使用串口中断了。

    硬件设计

    在开发板上,含有一个USB 转串口,一个RS232 串口,其硬件电路如图所示:

    在这里插入图片描述
    在这里插入图片描述

    PZ6806L 开发板串口3 电路:
    在这里插入图片描述
    从图中可以看出,通过CH340 芯片把STM32F1 的串口1 与 PC 机的USB 口进行连接,实现串口通信。根据前面介绍,串口通信需将数据收发管脚交叉连接,所以可以看到在CH340 芯片的2 和3 脚已做处理。电路中其他部分是自动下载电路部分,目的是控制BOOT 的启动模式与复位。
    STM32F1 使用的是串口3,即PB9 和PB10 管脚。此电路是按照RS232 接口标准搭建,使用了一个DB9 的母头,电平转换芯片使用的是SP3232,与MAX3232 一样。母头可作为下位机和上位机PC 进行串口通信,需使用交叉型串口线。电路中还有一个P232 插针,它是用来选择是USART3 功能还是IIC2 功能,如果我们需要使用这个DB9 做串口通信,需将P232 插针的3、5 短接,4、6 短接,如果做EEPROM 实验时需将P232 插针的1、3 短接,2、4 短接,开发板出厂时P232 插针默认选择的是IIC2 功能。

    本章实验所采用的是串口1 与PC 机USB 口进行通信,只需使用一根USB 线连接电脑USB 口即可实现串口通信。若大家需要使用DB9 接口,可以选择图2 电路,此时使用的是串口3,程序和串口1 通信是类似的,只需修改串口号即可。

    软件设计

    所要实现的功能是:STM32F1 通过USART1 实现与PC 机对话,STM32F1的USART1 收到PC 机发来的数据后原封不动的返回给PC 机显示。同时使用D1指示灯不断闪烁提示系统正常运行。程序框架如下:
    (1)初始化USART1,并使能串口接收中断等
    (2)编写USART1 中断函数
    (3)编写主函数
    在前面介绍串口配置步骤时,就已经讲解如何初始化串口。

    USART1 初始化函数
    要使用串口中断,我们必须先对它进行配置。USART1 初始化代码如下:

    /****************************************************************
    ***************
    * 函数名: USART1_Init
    * 函数功能: USART1 初始化函数
    * 输入: bound:波特率
    * 输出: 无
    *****************************************************************
    **************/
    void USART1_Init(u32 bound)
    {
    //GPIO 端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    
    /* 配置GPIO 的模式和IO 口*/
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA,&GPIO_InitStructure); 
    /* 初始化串口输入IO */
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入
    GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
    
    //USART1 初始化设置
    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_Cmd(USART1, ENABLE); //使能串口1
    USART_ClearFlag(USART1, USART_FLAG_TC);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
    
    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1 中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;// 抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC 寄存器
    }
    

    在USART1_Init()函数中,首先使能USART1 串口及端口时钟,并初始化GPIO为复用功能。其次配置串口结构体USART_InitTypeDef,使能串口并开启接收中断,为了防止串口发送状态标志位的影响,我们清除下串口状态标志位(TC),最后配置相应的NVIC 并使能对应中断通道,我们将USART1 的抢占优先级设置为3,响应优先级设置为3。这一过程在前面步骤介绍中已经提了。USART1_Init()函数有一个参数bound,用来设置USART1 串口的波特率,方便大家修改。 USART1 中断函数初始化USART1 后,接收中断就已经开启了,当上位机发送数据过来,STM32F1的串口接收寄存器内即为非空,触发接收中断,具体代码如下:

    /****************************************************************
    ***************
    * 函数名: USART1_IRQHandler
    * 函数功能: USART1 中断函数
    * 输入: 无
    * 输出: 无
    *****************************************************************
    **************/
    
    void USART1_IRQHandler(void) //串口1 中断服务程序
    {
    u8 r;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
    {
    r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
    USART_SendData(USART1,r);
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
    }
    USART_ClearFlag(USART1,USART_FLAG_TC);
    }
    

    为了确认USART1 是否发生接收中断,调用了读取串口中断状态标志位函数USART_GetITStatus,如果确实产生接收中断事件,那么就会执行if 内的语句,将串口接收到的数据保存在变量r 内,然后有通过串口发送出去,通过USART_GetFlagStatus 函数读取串口状态标志,如果数据发送完成,则退出while循环语句,且清除发送完成状态标志位USART_FLAG_TC。

    主函数
    编写好串口初始化和中断服务函数后,接下来就可以编写主函数了,代码如下:
    /****************************************************************
    ***************
    * 函数名: main
    * 函数功能: 主函数
    * 输入: 无
    * 输出: 无
    *****************************************************************
    **************/
    int main()
    {
    	u8 i=0;
    	SysTick_Init(72);
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组分2 组
    	LED_Init();
    	USART1_Init(9600);
    	while(1)
    	{
    		i++;
    		if(i%20==0)
    		{
    			led1=!led1;
    		}
    		delay_ms(10);
    		}
    }
    

    主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括SysTick 系统时钟,中断分组,LED 初始化等。然后调用我们前面编写的USART1初始化函数,这里我们设定串口通信波特率为9600。最后进入while 循环语句,不断让D1 指示间隔200ms 闪烁。如果发生接收中断事件,即会进入中断执行,执行完后回到主函数内继续运行。其实如果你学会了USART1 的使用,对于其他的串口都是类似的。

    展开全文
  • 文档介绍:编程实验报告实验题目:串口通信班级:学号:姓名:日期:2015-6-8一、实验要求把两台计算机的串口通过串口线连在一起,通过串口实现两台计算机通讯。可以利用高级语言、C语言编程实现,要求程序界面友好,有发送...

    文档介绍:

    编程实验报告实验题目:串口通信班级:学号:姓名:日期:2015-6-8一、实验要求把两台计算机的串口通过串口线连在一起,通过串口实现两台计算机通讯。可以利用高级语言、C语言编程实现,要求程序界面友好,有发送和接收功能,其接收和发送内容可在屏幕上显示。二、实验原理串口通讯把数据的字节分解成单个的二进制比特流依次传输,其结构简单,连接线少,应用非常广泛。实现串口通信的方法很多。如:利用标准通信函数实现串口通信、利用API实现串口通信和利用ActiveX控件实现。municationsControl(m)编程,Windows平台先进的ActiveX技术使得对串口编程不再需要处理烦琐的细节。利用已有的AxtiveX控件,只需要编写少量的代码,就可以轻松高效地完成任务。以下对ActiveX控件属性进行简单介绍,在ClassWizard中为新创建的通信控件定义成员对象(m),通过该对象便可以对串口属性进行设置,m控件共有27个属性,mPort:设置并回通讯端口号,l。Settings:以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。PortOpen:设置并返回通讯端口的状态,也可以打开和关闭端口。Input:从接收缓冲区返回和删除字符。Output:向发送缓冲区写一个字符串。InputLen:设置每次Input读入的字符个数,缺省值为0,表明读取接收缓冲区中的全部内容。InBufferCount:返回接收缓冲区中已接收到的字符数,将其置0可以清除接收缓冲区。InputMode:定义Input属性获取数据的方式(为0:文本方式;为1:二进制方式)。RThreshold和SThreshold:m事件发生之前,接收缓冲区或发送缓冲区中可以接收的字符数。三、实验步骤1、建立应用工程启动VC++6.0,创建一个基于对话框的MFC应用程序项目,ponentsandControls选项,在弹出的对话框中双击RegisteredActiveXControls项,则所有注册过的ActiveX控件出现在列表框中。municationsCon—trolversion6.0,单击insert按钮即可将通信控件插入该工程。添加该控件到对话框中,M.2、添加界面控件将对话框中的按钮“取消”删除,将“确定”按钮改为“退出”。在对话框中添加适当的界面控件。本实验中需添加的标注用的静态控件、BO_BTLSET、添加控制开始发送/接收按钮控件并设置控件ID号为IDC_BUTTON_START,添加用于输入发送数据和输出接收数据的编辑框并设置控件ID号为IDC_EDIT_SEND和IDC_EDIT_RECEVE,同时为其设置各种属性。添加完后如下图:3、映射控件通用消息(1)lassWizard对话框,单击MemberValuable为相应控件添加变量。添加变量名和类型如下表:m如下图:(2)单击MessageMaps,M_TDlg::OnInitDialog();编辑加入代码如下:M_TDlg::OnInitDialog(){ //TODO:Addextrainitializationhere select.AddString("COM1");//为组合框设置选项,即设定串口选项 select.AddString("COM2"); select.AddString("COM3"); se

    内容来自淘豆网www.taodocs.com转载请标明出处.

    展开全文
  • 串口通信实验

    千次阅读 2016-09-12 11:50:42
     USART串口通信配置一,串口操作相关库函数:获取状态标志位函数-操作USART_SR寄存器// 获取状态标志位 FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); // 清除状态标志位 void ...
  • USART串口通信实验

    2021-05-26 19:36:04
    文章目录串口简介串口通信基本原理常用串口相关寄存器串口操作相关函数硬件连接串口配置一般步骤例程参考升级版 串口简介 详情见STM32F4开发指南 串口通信基本原理 常用串口相关寄存器 1、USART_SR状态寄存器 2、...
  • VC串口通信实验

    2019-09-23 17:17:14
    实验一:VC串口通信实验 一、实验目的 通过实验让学生了解串口通信的工作原理。 二、实验器材 计算机两台 串口连接线一根GND(pin5) GND(pin5) TXD(pin3)RXD(pin2) RXD(pin2)TXD(pin3) RTS(pin7)CTS(pin8)...
  •   在树莓派基础实验35:USB TO TTL模块实验中学习了通过串口对树莓派进行控制台控制,让串口作为控制终端调试口即 serial console,但是在项目中常常会使用串口同其他传感器、单片机等设备进行通用串口通信。...
  • STM32串口通信实验

    2020-10-27 17:35:14
    DB9接口指9针的接口(串口连接器) USART_InitTypeDef.USART_BaudRate //波特率 USART_InitTypeDef.USART_WordLength //字长 USART_InitTypeDef.USART_StopBits //停止位 USART_InitTypeDef.USART_Parity //奇偶校验位...
  • 串口通信实验讲解

    2020-02-24 13:46:38
    STM32串口常用寄存器和库函数 串口操作相关库函数(省略入口参数): void USART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能 void USART_Cmd();//使能串口 void USART_ITConfig();...
  • STM32F103 串口通信实验

    千次阅读 2020-06-04 09:54:47
    串口通信是一种设备很常用的串口通讯方式,串口按位(bit)发送和接受字节,尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据,大部分电子设备都支持该通讯设备,作为...
  • 嵌入式课程 之 中断和串口通信实验

    千次阅读 2019-09-24 23:16:31
    文章目录【实验目的】【实验原理】一、USART接口简介二、串口通信分类及原理三、硬件连接和USART库函数介绍四、软件流程图【实验环境】操作系统:设备简介:【实验步骤】一、配置工程环境二、开启时钟...
  • 在树莓派基础实验35:USB TO TTL模块实验中学习了通过串口对树莓派进行控制台控制,让串口作为控制终端调试口即 serial console,但是在项目中常常会使用串口同其他传感器、单片机等设备进行通用串口通信。 本实验...
  • 单片机串口通信实验

    千次阅读 2009-06-10 11:59:00
    实验四 单片机串口通信实验姓 名:郑旅军 学 号:0656061指导老师:邹慧兰 成 绩:如有疑问,请zlj800800@163.com 探讨 一、实验目的1学习单片机串口工作方式的程序设计2学习串行通信的协议3学习串口通信的...
  • stm32入门——串口通信实验

    千次阅读 2018-12-02 15:31:58
    stm32入门——串口通信实验 基础概念 同步:在时钟信号下进行信息的传输,比如在每个时钟的上升沿进行一次传输。 异步:不用与时钟一起传输,但若想传输成功,传送方与接收方必须约定好传送速度——波特率。 单工:...
  • RS485串口通信实验

    2020-12-09 18:48:31
    RS-485简介 RS-232是单端输入输出,而RS-422/485为差分输入输出。 单端传输是指在发送或接收过程中,用信号线对地线的电压值来表示逻辑“0”和“1”。 差分传输使用两根信号线来...实验任务 使用两块开拓者开发板通过.
  • 基于STM32的UART串口通信实验 一 串口通信原理: 1.1 本实验实现串口助手发送数据然后回送在串口助手呈现出来。1.2 实验思路:看懂电路图,理解uart串口通信原理。1.3 开发环境 : MDK5 库函数版本开发 JLINK仿真 二...
  • ARM基本接口之串口通信实验

    千次阅读 2018-05-26 18:03:46
    ARM基本接口之串口通信实验实验目的:1.掌握ARM的串行口工作原理;2. 学习并编程实现ARM的UART通信;3. 掌握S3C2440寄存器配置方法。实验步骤:1. 总体步骤:先编译,打开超级终端,启动目标机,待显示2440后,进行...
  • 双单片机串口通信实验 一、实验目的 二、实验内容 三、实验步骤 四、C代码如下 五、实验结果 六、实验体会 一、实验目的 1、 掌握单片机串口通信的设计方法; 2、 了解双单片机通信的原理。 二、实验内容...
  • 物联网系统安装调试课程 电信工程系 串口通讯实验 物联网专业 目 录 项目要求 01 工具设备 02 项目的原理及步骤 03 结果现象 04 1.项目要求 通过本实验熟悉Z-Stack协议栈对串口的操作 通过本实验熟悉Z-Stack协议栈对...
  • 这几天使用xilinx的zynq-7000系列调试rs422串口,期间遇到不少问题,好在最终调试完成,在这里记录一下调试步骤。 我用的soc型号是xc7z100,板载了2个rs422外设,PS端有2个uart控制器,uart0用于连接rs232并作为...
  • STM32中USART串口通信实验

    千次阅读 2020-12-02 14:37:18
    UART即通用异步收发器,它是在USART基础上裁剪掉了同步通信功能,同 步和异步主要看其时钟是否需要对外提供,这个前面也介绍了。我们开 发板上使用的STM32F103ZET6芯片含有3个USART,2个UART外设
  • USART 串口通信配置步骤在上面的介绍中,可能有的朋友很不理解,不过没有关系,下面我们讲解如何使用库函数对 USART 进行配置。这个也是在编写程序中必须要了解的。具体步骤如下:(USART 相关库函数在 stm32f10x_...
  • 单片机与 PC 机串口通信实验

    千次阅读 多人点赞 2019-01-22 17:57:24
    实验原理 51 单片机的串行口是一个可编程的全双工的通信接口,具有 UART(通用异步收发器)的全部功能,能同时进行数据的发送和接收,也可以作为同步移位寄存器使用。51 单片机的串行口主要有两个独立的串行数据...
  • 51单片机学习笔记【六】——串口通信实验

    万次阅读 多人点赞 2015-07-22 01:06:37
    串口通信基础1.串行通信 串行通信将数据字节分成一位一位的形式在一条传输线上逐个传送。单片机采用串行通信。特点是:传输线少,长距离传送成本低,但数据传送控制复杂。 串行通信的传输的传输方向:单工(数据传输...
  • 《计算机网络》实验1基本串口通信.doc 上传人:带****文档编号:76172851上传时间:2020-04-28格式:DOC页数:3大小:72.50KB下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览、不比对内容而直接...
  • 基于STM32完成串口通信一、概述:二、库函数与寄存器的区别1、库函数与寄存器的区别:2、代码对比:总结3、两种方式所需要的库的区别总结三、STM32的串口通信USART1、构建添加需要的库2、usart_init函数:3、主函数...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,175
精华内容 1,670
关键字:

串口通信实验步骤