精华内容
下载资源
问答
  • 1.5串口通信实验

    2021-02-01 10:19:42
    串口配置的一般步骤串口时钟的使能,GPIO口时钟的使能; 串口复位(非必须); GPIO端口模式设置; 串口参数初始化; 开始中断并且初始化NVIC; 使能串口; 编写中断处理函数; 串口数据的收发; 串口...

    串口配置的一般步骤:

    1. 串口时钟的使能,GPIO口时钟的使能;
    2. 串口复位(非必须);
    3. GPIO端口模式设置;
    4. 串口参数初始化;
    5. 开始中断并且初始化NVIC;
    6. 使能串口;
    7. 编写中断处理函数;
    8. 串口数据的收发;
    9. 串口传输状态的获取;

    部分步骤如下:

    void MF_UART0_Init(void)//初始化函数
    {

        FL_GPIO_InitTypeDef    GPIO_InitStruct;//GPIO口初始化

        FL_UART_InitTypeDef    defaultInitStruct;

        GPIO_InitStruct.pin = FL_GPIO_PIN_3;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = DISABLE;
        GPIO_InitStruct.remapPin = DISABLE;

        FL_GPIO_Init( GPIOA, &GPIO_InitStruct );

        GPIO_InitStruct.pin = FL_GPIO_PIN_2;
        GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
        GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.pull = DISABLE;
        GPIO_InitStruct.remapPin = DISABLE;

        FL_GPIO_Init( GPIOA, &GPIO_InitStruct );

      -----------------------------------------串口的初始化

        defaultInitStruct.clockSrc = 0;  //时钟源选择
        defaultInitStruct.baudRate = 115200;//设置波特率
        defaultInitStruct.dataWidth = FL_UART_DATA_WIDTH_8B; //字长为8位数据模式
        defaultInitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B;//一个停止位
        defaultInitStruct.parity = FL_UART_PARITY_EVEN;//偶校验
        defaultInitStruct.transferDirection = FL_UART_DIRECTION_TX_RX;//收发模式

        FL_UART_Init(UART0,&defaultInitStruct );//

        
    }

    ErrorStatus FL_UART_DeInit(UART_Type *UARTx)
    {
        ErrorStatus status = PASS;

        /* 参数入口合法性 */
        assert_param(IS_UART_INSTANCE(UARTx));
        
        /* 外设复位使能 */
        FL_RCC_EnablePeripheralReset();
        
        if (UARTx == UART0)
        {
            /*复位UART*/
            FL_RCC_EnableResetAPB2Peripheral(FL_RCC_RSTAPB_UART0);
            FL_RCC_DisableResetAPB2Peripheral(FL_RCC_RSTAPB_UART0);
            
            /* 外设总线时钟关闭 */
            FL_RCC_DisableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART0);
            
            /* 外设操作时钟关闭 */
            FL_RCC_DisableGroup1OperationClock(FL_RCC_GROUP1_OPCLK_UART0);
        }
        else if (UARTx == UART1)
        {
            /*复位UART*/
            FL_RCC_EnableResetAPB2Peripheral(FL_RCC_RSTAPB_UART1);
            FL_RCC_DisableResetAPB2Peripheral(FL_RCC_RSTAPB_UART1);
            
            /* 外设总线时钟关闭 */
            FL_RCC_DisableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART1);
            
            /* 外设操作时钟关闭 */
           FL_RCC_DisableGroup1OperationClock(FL_RCC_GROUP1_OPCLK_UART1);
        }
        else if (UARTx == UART4)
        {
            /*复位UART*/
            FL_RCC_EnableResetAPB1Peripheral(FL_RCC_RSTAPB_UART4);
            FL_RCC_DisableResetAPB2Peripheral(FL_RCC_RSTAPB_UART4);
            
            /* 外设总线时钟关闭 */
            FL_RCC_DisableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART4);
        }
        else if (UARTx == UART5)
        {
            /*复位UART*/
            FL_RCC_EnableResetAPB1Peripheral(FL_RCC_RSTAPB_UART5);
            FL_RCC_DisableResetAPB1Peripheral(FL_RCC_RSTAPB_UART5);
            
            /* 外设总线时钟关闭 */
            FL_RCC_DisableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART5);
        }
        else
        {
            status = FAIL;
        }
        
        /* 锁定外设复位功能 */
        FL_RCC_DisablePeripheralReset();
        
        return (status);
    }

    /**
      * @brief    配置UART
      *               
      * @param    UARTx  外设入口地址
      * @param     initStruct 指向 @ref FL_UART_InitTypeDef 结构体的指针      
      *         
      * @retval    错误状态,可能值:
      *            -PASS 配置成功
      *            -FAIL 配置过程发生错误    
      */
    ErrorStatus FL_UART_Init(UART_Type *UARTx, FL_UART_InitTypeDef *initStruct)
    {
        ErrorStatus status = FAIL;
        uint32_t Fclk=0,baudRate=0;

        /* 参数合法性检查 */
        assert_param(IS_UART_INSTANCE(UARTx));
        assert_param(IS_FL_UART_CLKSRC(initStruct->clockSrc));
        assert_param(IS_FL_UART_DATAWIDTH(initStruct->dataWidth));
        assert_param(IS_FL_UART_PARITY(initStruct->parity));
        assert_param(IS_FL_UART_STOPBITS(initStruct->stopBits));
        assert_param(IS_FL_UART_DIRECTION(initStruct->transferDirection));

        if(UARTx == UART0)
        {
            /*时钟源选择*/
           FL_RCC_SetUART0ClockSource(initStruct->clockSrc);
            
            /* 根据不同的时钟源计算baudrate 寄存器值,并配置 */
            switch(initStruct->clockSrc)
            {
                case FL_RCC_UART0_CLK_SOURCE_APB1CLK:
                    Fclk = FL_RCC_GetAPB1ClockFreq();
                    break;    
                case FL_RCC_UART0_CLK_SOURCE_RCHF:
                    Fclk = FL_RCC_GetRCHFClockFreq();
                    break;
                case FL_RCC_UART0_CLK_SOURCE_SYSCLK:
                    Fclk = FL_RCC_GetSystemClockFreq();
                    break;
                 case FL_RCC_UART0_CLK_SOURCE_RCMF_PSC:
                    Fclk = FL_RCC_GetRC4MClockFreq();
                    break;
            }  
            
                    baudRate = Fclk/initStruct->baudRate - 1;
        }   
      
       if(UARTx == UART1)
        {
            /*时钟源选择*/
           FL_RCC_SetUART1ClockSource(initStruct->clockSrc);
            
            /* 根据不同的时钟源计算baudrate 寄存器值,并配置 */
            switch(initStruct->clockSrc)
            {
                case FL_RCC_UART1_CLK_SOURCE_APB1CLK:
                    Fclk = FL_RCC_GetAPB1ClockFreq();
                    break;    
                case FL_RCC_UART1_CLK_SOURCE_RCHF:
                    Fclk = FL_RCC_GetRCHFClockFreq();
                    break;
                case FL_RCC_UART1_CLK_SOURCE_SYSCLK:
                    Fclk = FL_RCC_GetSystemClockFreq();
                    break;
                 case FL_RCC_UART1_CLK_SOURCE_RCMF_PSC:
                    Fclk = FL_RCC_GetRC4MClockFreq();
                    break;
            }  
            
                    baudRate = Fclk/initStruct->baudRate - 1;
        }
             
        if(UARTx == UART0)
        {
            /*总线时钟使能*/
            FL_RCC_EnableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART0);
            
            /*操作时钟使能,使能串口*/
            FL_RCC_EnableGroup1OperationClock(FL_RCC_GROUP1_OPCLK_UART0);
              
        }
        else if(UARTx == UART1)
        {
            /*总线时钟使能*/
            FL_RCC_EnableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART1);
            
            /*操作时钟使能*/
            FL_RCC_EnableGroup1OperationClock(FL_RCC_GROUP1_OPCLK_UART1);
        }
        else if(UARTx == UART4)
        {
            /*总线时钟使能*/
            FL_RCC_EnableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART4);
            Fclk = FL_RCC_GetAPB2ClockFreq();
            baudRate = Fclk/initStruct->baudRate - 1;
            
        }
         else if(UARTx == UART5)
            {
            FL_RCC_EnableGroup3BusClock(FL_RCC_GROUP3_BUSCLK_UART5);
            Fclk = FL_RCC_GetAPB2ClockFreq();
            baudRate = Fclk/initStruct->baudRate - 1;
        }
                    
        /*发送接收控制*/
        if(initStruct->transferDirection&FL_UART_DIRECTION_TX)
        {
            FL_UART_EnableTX(UARTx);
        }
        if(initStruct->transferDirection&FL_UART_DIRECTION_RX)
        {
            FL_UART_EnableRX(UARTx);
        }
             
        /*配置波特率*/
        FL_UART_WriteBaudRate(UARTx,baudRate);
        
        /*配置停止位长度*/
        FL_UART_SetStopBitsWidth(UARTx,initStruct->stopBits);
        
        /*数据长度*/
        FL_UART_SetDataWidth(UARTx,initStruct->dataWidth);
        
        /*配置奇偶校验*/
        FL_UART_SetParity(UARTx,initStruct->parity);
        
        status = PASS;
        return status;
    }
     

    展开全文
  • STM32F103 串口通信实验

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

    实验目的

    通过本实验的学习,掌握STM32的串口使用,实现通过串口发送和接受数据。

    实验简介

    串口通信是一种设备很常用的串口通讯方式,串口按位(bit)发送和接受字节,尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据,大部分电子设备都支持该通讯设备,作为计算机与单片机交互数据的主要接口,广泛用于各类仪器仪表,工业检测以及自动控制领域,通信协议是需要通信的双方所达成的一种约定,它对包括数据格式,同步方式,传送速度,传送步骤,检纠错方式以及控制字符定义等问题作出统一的规定,通信双方都必须共同遵守。

    串口通讯我们一般分为物理层和协议层,物理层规定通讯系统中具有机械,电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包,解包标准。

    物理层:就是最底层的电平信号传输,大家熟知的RS232,RS485这些芯片,就是实现的物理层的电平转换,将单片机的TTL电平,转换成相应的接口电平。

    星光枭龙STM32F103开发板,板载了一个USB转串口芯片,将TTL信号转成USB接口的差分信号,这也算是一种物理层芯片。

    串口通信分为单工,半双工,全双工,取决于物理层的收发芯片:
    单工:只能由一方A传到另一方B。
    半双工:可以双向传输,但不能同时存在。

    全双工:可以同时存在双向传输

    协议层:串口传输一个字符的格式分为起始位,数据位,奇偶校验位,停止位和空闲位。
    起始位:发出一个逻辑“0”信号,表示传输字符开始。
    数据位:紧接在起始位之后,数据为的个数可以是5,6,7,8,一般采用8位,首先传送最低位。
    奇偶校验位:奇偶校验是串口通信的一种简单纠错方式,数据位加上这一位后,使得1的位数是偶数(偶校验)或奇数(奇校验),
    停止位:它是一个字符数据传输结束的标志位,可以是1位,1.5位,2位的高电平
    空闲位:处于逻辑“1”状态,表示当前传输线路上没有数据。

    电路设计

    星光STM32F103开发板板载一个USB串口,芯片采用CH340G,接口采用MINI USB接口,连接STM32的USART1的PA9 PA10.

    在这里插入图片描述

    寄存器代码

    usart.h

    #ifndef __USART_H
    #define __USART_H
    
    #include "sys.h"
    #include "stdio.h"
    
    #define USART_REC_LEN  200
    //定义最大接收字数
    #define EN_USART1_RX 1
    //使能1 禁止 0
    
    extern u8 USART_RX_BUF[USART_REC_LEN];
    //接收缓冲最大为USART_REC_LEN个字节
    extern u16 USART_RX_STA;
    //接收状态标记
    
    void uart_init(u32 pclk2,u32 bound);
    //PCLK2时钟频率  波特率
    #endif
    

    usart.c

    #include "usart.h"
    
    #if SYSTEM_SUPPORT_OS
    #include "includes.h"
    //ucos 使用
    #endif
    
    #if 1
    #pragma import(__use_no_semihosting)
    
    struct __FILE
    {
    	int handle;
    };
    
    FILE __stdout;
    
    _sys_exit(int x)
    {
    	x=x;
    }
    
    int fputc(int ch,FILE *f)
    //重定向fputc函数
    //printf的输出,指向fputc,由fputc输出到串口
    //这里使用串口1(USART1)输出printf信息
    {
    	while((USART1->SR&0x40) == 0);
    	//等待上一次串口数据发送完成
    	USART1->DR = (u8)ch;
    	//写DR,串口1将发送数据
    	return ch;
    }
    
    #endif
    
    #if EN_USART1_RX
    //如果使能了接收
    u8 USART_RX_BUF[USART_REC_LEN];
    //接收缓冲
    u16 USART_RX_STA = 0;
    //接收状态标记
    void USART1_IRQHandler(void)
    {
    	u8 res;
    	#if SYSTEM_SUPPORT_OS
    	//如果SYSTEM_SUPPORT_OS为真
    	OSIntEnter();
    	#endif
    	
    	if(USART1->SR&(1<<5))
    	//接收到数据
    	{
    		res = USART1->DR;
    		//将接收到的数据存在res中
    		if((USART_RX_STA&0x8000)==0)
    		//接收未完成
    		{
    			if(USART_RX_STA&0x4000)
    			//接收到了0x0d,换行符0x0d+0x0a
    			{
    				if(res != 0x0a)
    					USART_RX_STA = 0;
    				//接收错误,重新开始
    				else
    					USART_RX_STA |= 0x8000;
    				//接收完成了
    			}
    			else//还没收到0x0d;
    			{
    				if(res == 0x0d)
    				//如果收到0x0d
    					USART_RX_STA |=0x400;
    				else
    				{
    					USART_RX_BUF[USART_RX_STA&0x3FFF] = res;
    					USART_RX_STA++;
    					if(USART_RX_STA>(USART_REC_LEN-1))
    					USART_RX_STA = 0;	
    				}
    			}
    		}
    	}
    
    
    #if SYSTEM_SUPPORT_OS
    //如果SYSTEM_SUPPORT_OS 为真,则需要支持OS
    OSIntExit();
    #endif
    }
    #endif
    
    void uart_init(u32 pclk2,u32 bound)
    //初始化IO (PCLK2时钟频率,波特率)
    {
    	float temp;
    	u16 mantissa;
    	u16 fraction;
    	temp = (float)(pclk2*1000000)/(bound*16);
    	//得到USARTDIV
    	mantissa = temp;
    	//得到整数部分
    	fraction = (temp-mantissa)*16;
    	//得到小数部分
    	mantissa<<=4;
    	mantissa += fraction;
    	RCC->APB2ENR |= 1<<2;
    	//使能PORTA口时钟
    	RCC->APB2ENR |= 1<<14;
    	//使能串口时钟
    	GPIOA->CRH &= 0xFFFFF00F;
    	GPIOA->CRH |= 0x000008B0;
    	//PA17 18 IO状态设置,一接收,一发送
    	RCC->APB2RSTR |= 1<<14;
    	//复位串口1
    	RCC->APB2RSTR &= ~(1<<14);
    	//停止复位
    	USART1->BRR = mantissa;
    	//波特率设计
    	USART1->CR1 = 0x200C;
    	//1停止位,无校验位,接收发送使
    	#if EN_USART1_RX
    	//如果使能了接收
    	USART1->CR1 |= 1<<5;
    	//接收缓冲区非空中断使能
    	MY_NVIC_Init(3,3,USART1_IRQn,2);
    	//中断初始化
    	#endif
    }
    
    
    

    HAL库代码

    main.c

    #include "MyIncludes.h"
    
    #define RECV_LENGTH 100
    //接受缓冲长度
    #define SEND_LENGTH 100
    //发送缓冲长度
    
    u8 test_txbuf[100];
    //发送数组
    u8 test_rxbuf[100];
    //接收数组
    u8 tx_index = 0;
    u8 send_len;
    //发送长度
    u8 recv_len;
    //接受长度
    u8 recv_timeout = 0; 
    //接受超时
    u8 recv_complete = 0;
    //接受完成
    
    u16 sys_cnt = 0;
    void systick_isr(void)
    {
      if(sys_cnt <100 )
      sys_cnt++;
      else
      {
        sys_cnt = 0;
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
      }
      if( recv_timeout <30 )
      recv_timeout++;
      if(recv_timeout ==20 )
      {
       recv_complete = 1;
      }
      //systick定时器的作用:
      //PC4 PC5灯亮,并让接受超时recv_timeout
      //运行,如果超过20 则说明发送完成
    } 
    u8 rx_index;
    void uart_rx(unsigned char RxData)
    //作用将接收的数据存放在text_rxbuf[]
    //函数中,
    {
     if( rx_index < RECV_LENGTH )
     {
       test_rxbuf[rx_index++] = RxData;
     }
     recv_timeout = 0;
     //接收超时计数器清零
    }
    
    void Uart_Fill_Tx(u8 *buf,u8 len)
    //发送数据函数
    {
      u8 i;
      send_len = len;
      if(len > sizeof(test_txbuf))
      send_len = sizeof(test_txbuf);
      //这两行是为了确保长度要小于100
      //也就是上面的
      for( i=0; i<send_len; i++)
      {
       test_txbuf[i] = *buf++;
      }
      //将接收到的赋值于要发送的数组中
      tx_index = 0;
      //为下次做准备
      USART1_Send(test_txbuf,send_len);
      //发送函数,两个参数,发送数组(指针)
      //和发送长度
    }
    
    void Uart_RecvProcess(void)
    //接收数据函数
    {
     if(recv_complete == 1)
     //接收完成等于1 接收完成
     {
      recv_complete = 0;
      //赋值为零为下次做准备
      recv_len = rx_index;
      //得到接收数组的长度
      rx_index = 0;
      Uart_Fill_Tx(test_rxbuf,recv_len);
      //发送函数,两个参数 ,接收数组,以及
      //接收数组的长度
     }
    }
    
    int main(void)
    {
     System_Init();
     LED_Init();
     SysTick_Init(systick_isr);
     recv_timeout = 150;
     //初始化超时值
     USART1_Init(115200,NULL,uart_rx);
     //串口1初始化  3个参数  分别是波特率115200
     //发送完成回调为空    和接受回调uart_rx;
     while(1)
     {
       Uart_RecvProcess();
       //接受处理函数
       Key_Read();
       if(Key_Info.Num_Last != Key_Info.Num)
       {
         Key_Info.Num_Last = Key_Info.Num;
    
         if(Key_Info.Num != 0)
         {
          switch(Key_Info.Num)
          {
            case KEY_ONE:
            printf("STM32F103 USART1 TEST!!!\r\n");
            //这个迷茫了一下,这里应该是单片机发送数据
            break;
            default:break; 
          }
         }
       }
     }
    }
    /*因为本人水平有限,所以刚看的时候有点懵,刚开
    始看代买的时候,如果水平高怎么看都可以,如果感
    觉到很懵,我建议就是从main()函数中看起,就像
    这个main.c,我们从main()开始看:首先是系统初
    始化,LED初始化,然后滴答定时器函数,我们看滴答
    定时器:发现作用就是短时间内反转PC4 PC5灯,然后
    如果接收超时大于等于30没改变,小于30 每运行一次
    接收超时加一,等于20的时候就说明不再发送那么接收完成变为1 ,
    我目前觉得作用就是让接受超时recv_timeout运行,在20以内,
    就是还在发送,否则发送完成,然后main()函数的下一行代码,
    初始化超时值150,在这里150大于30,如果没有运行串口通信
    150就不会归零,也就是systick定时器里的recv_timeout
    就不会运行然后下一个函数USART1_Init(115200,NULL,uart_rx);
    串口通信初始化,我们先不用了解里面是怎么样运行的
    主要了解函数内里这三个参数 波特率 115200 ,发送
    回调函数 但是为空,也就是不用管这个,以及函数指针
    uart_rx()函数,然后我们看这个函数,这个函数的作用
    是将接收到的RECV_LENGTH(100)以内的数据存在test_rxbuf【】
    数组中,并记录个数rx_index++,因为每次接受到了数据,
    所以要将超时计数器清零,然后Uart_RecvProcess();这个函数
    如果接收完成,为下次做准备,并将接收到的数据发送出去
    也就是Uart_Fill_Tx(test_rxbuf,recv_len)这个函数,发送的
    数据在sizeof(test_txbuf)以内,test_txbuf[100]也就是100个
    数据,然后将接收到的数据赋值于发送数组中,然后发送
    USART1_Send(test_txbuf,send_len)*/
    
    
    

    Usart.h

    #ifndef __USART_H_
    #define __USART_H_
    
    #include "stm32f1xx.h"
    #include "stm32_types.h"
    #include "stm32f1xx_hal.h"
    
    #define UART_LSR_RDR (1<<5)
    //接收逻辑右移       100000(32)
    #define UART_LSR_THRE (1<<6)
    //发送逻辑右移       1000000(64)
    #define SEND_BUF1 (USART1->DR)
    //      发送缓冲区 串口1的数据寄存器 
    #define RECV_BUF1 (USART1->DR)
    //      接收缓冲区 串口1的数据寄存器
    #define USART1_SR (USART1->SR)
    //      串口1的状态寄存器
    #define USART1_TX_ISR_ENABLE() (USART1->CR1 |=(1<<6))
    //      串口1 发送 中断 使能    1000000(64)
    #define USART1_TX_ISR_DISABLE() (USART1->CR1 &=~(1<<6))
    //      串口1 发送 中断 禁能    100000 (64)
    typedef struct
    {
      void (*U1TXOver)(void);
      //发送完成回调函数指针
      void (*U1RXOperation)(unsigned char RxData);
      //接收回调函数指针
      
    }_USART_ISR_;
    
    extern _USART_ISR_ Usart_ISR;
    
    void USART1_Init(unsigned int BPS,void (*TXFunction)(void),void(*RxFunction)(unsigned char RX_Data) );
    //串口初始化函数
    
    void USART1_Send(uint8_t *buff,uint16_t Size);
    //串口发送函数
    #endif
    /*Usart.h文件作为一个小白,感觉很多专有名词不懂,知道了就好。*/
    

    Usart.c

    #include "Usart.h"
    
    _USART_ISR_ Usart_ISR;
    
    UART_HandleTypeDef Uart1_Handle;
    //结构体声明
    void USART1_IRQHandker(void)
    //串口中断服务函数
    {
      unsigned long temp;
      temp = USART1_SR;
      if(temp&UART_LSR_RDR)
      //接收到数据
      {
        if(Usart_ISR.U1RXOperation != NULL)
        Usart_ISR.U1RXOperation(RECV_BUF1);
      }
      HAL_UART_IRQHandler(&Uart1_Handle);
      //使能中断,选定中断源
    }
    
    void USART1_Init(unsigned int BPS,void Tx_Over(void),void(*RxFunction)(unsigned char RX_Data))  
    //串口初始化   参数:波特率 发送回调函数 接收回调函数  
    {
     GPIO_InitTypeDef GPIO_InitStruct;
     //结构体声明
     Usart_ISR.U1TXOver = Tx_Over;
     //main.c中为NULL
     Usart_ISR.U1RXOperation = RxFunction;
     //main.c中的uart_rx()函数
    
     __GPIOA_CLK_ENABLE();
     //使能GPIOA时钟
     __USART1_CLK_ENABLE();
     //使能USART1时钟
    //USART1端口配置
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    //USART1对应的端口为PA9 TX
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    //复用开漏输出模式
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    //高速
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    //上拉
    HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
    //初始化PA9 PA10;
    
     GPIO_InitStruct.Pin = GPIO_PIN_10;
     //UASRT1对应的IO口PA10 RX
     GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
     //配置为复用开漏输入
     HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
     //初始化PA10
    
     Uart1_Handle.Instance = USART1;
     //串口1
     Uart1_Handle.Init.BaudRate = BPS;
     //波特率设置
     Uart1_Handle.Init.WordLength = UART_WORDLENGTH_8B;
     //字节长8位
     Uart1_Handle.Init.StopBits = UART_STOPBITS_1;
     //1个停止位l
     Uart1_Handle.Init.Parity = UART_PARITY_NONE;
     //无校验
     Uart1_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
     //无硬件流
     Uart1_Handle.Init.Mode = UART_MODE_TX_RX;
     //串口发送接收
     Uart1_Handle.Init.OverSampling = UART_OVERSAMPLING_16;
     //16倍过采样
     
     HAL_UART_Init(&Uart1_Handle);
     //初始化串口
     __HAL_UART_ENABLE_IT(&Uart1_Handle,UART_IT_RXNE);
     //使能接收中断
     HAL_NVIC_SetPriority(USART1_IRQn,0,1);
     //设置中断优先级
     HAL_NVIC_EnableIRQ(USART1_IRQn);
     //使能中断
     }
    void USART1_Send(uint8_t *buff,uint16_t Size)
    //串口发送
    {
     HAL_UART_Transmit_IT(&Uart1_Handle,(uint8_t*)buff,Size);
    }
    
    int fputc(int ch,FILE *f)
    //重定义fputc函数,重定向后可使用printf函数
    {
     while((USART1_SR&UART_LSR_THRE) == 0);
     //等待发送完成
     SEND_BUF1 = (u8) ch;
    return ch;
    }
    
    展开全文
  • ARM基本接口之串口通信实验

    千次阅读 2018-05-26 18:03:46
    ARM基本接口之串口通信实验实验目的:1.掌握ARM的串行口工作原理;2. 学习并编程实现ARM的UART通信;3. 掌握S3C2440寄存器配置方法。实验步骤:1. 总体步骤:先编译,打开超级终端,启动目标机,待显示2440后,进行...

    ARM基本接口之串口通信实验

    实验目的:

    1.掌握ARM的串行口工作原理;
    2. 学习并编程实现ARM的UART通信;
    3. 掌握S3C2440寄存器配置方法。

    实验步骤:

    1. 总体步骤:先编译,打开超级终端,启动目标机,待显示2440后,进行创建链接,下载, 运行。

     

    2. 实验过程:先连接超级终端,首次连接失败,原因是:硬件接口接触不良,换了一台电 脑后,成功连接。

    原来的代码是将字符接収和发送到超级终端上进行显示,通过简单的修改,将 原来代码中的ch = Uart_Getch();

    Uart_SendByte(ch);

    修改为:调用Uart_GetString();函数。完成了从接収字符并发送改为字符串的 接収与发送。

     

    3. 代码如下:

    //Main.c

    /* 包含文件 */
    
    #include "def.h"
    
    #include "2410lib.h"
    
    #include "option.h"
    
    #include "2410addr.h"
    
    #include "interrupt.h"
    
     
    
    /********************************************************************
    
    // Function name	: Main
    
    // Description	    : JXARM9-2410 串口通信实验主程序
    
    //                    实现功能:
    
    //                        实现JXRAM9-2410与PC机的串口通讯
    
    //                        JXARM9-2410 UART0 <==> PC COM
    
    // Return type	: void
    
    // Argument         : void
    
    *********************************************************************/
    
    void Main(void)
    
    {
    
    /* 配置系统时钟 */
    
        ChangeClockDivider(2,1);                                                
    
        U32 mpll_val = 0 ;
    
        mpll_val = (92<<12)|(1<<4)|(1);
    
        ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
    
        
    
        /* 初始化端口 */
    
        Port_Init();
    
        
    
        /* 初始化串口 */
    
        Uart_Init(0,115200);
    
        Uart_Select(0);
    
        
    
        /* 打印提示信息 */
    
     
    
    PRINTF("\n---UART测试程序---\n");
    
    PRINTF("\n请将UART0与PC串口进行连接,然后启动超级终端程序(115200, 8, N, 1)\n");
    
    PRINTF("\n从现在开始您从超级中断发送的字符将被回显在超级终端上\n");
    
        /* 开始回环测试 */
    
    while(1)
    
    {
    
    //unsigned char ch = 'a';
    
    //ch = Uart_Getch();
    
    //Uart_SendByte(ch);
    
    Uart_GetString();
    
    //if(ch == 0x0d)
    
    //Uart_SendByte(0x0a);
    
    }
    
    }
    
     
    2440lib.c
    回车,ASCII码13   
    换行,ASCII码10  
    在Windows中:
    '\r'  回车,回到当前行的行首,而不会换到下一行;
    '\n'  换行,换到当前位置的下一行,而不会回到行首
    
     
    
    /********************************************************************
    
    // Function name	: Uart_GetString
    
    // Description	    : 从串口接收一个字符串,以回车键结束
    
    // Return type	: void
    
    // Argument         : char *string:收到的字符串
    
    *********************************************************************/
    
    void Uart_GetString(char *string)
    
    {
    
        char *string2 = string;
    
        char c;
    
        while((c = Uart_Getch())!='\r')
    
        {
    
            if(c=='\b')//退格 (删除一个字符)
    
            {
    
                if( (int)string2 < (int)string )
    
                {
    
                    Uart_Printf("\b \b");
    
    //先移动光标到前一个字符处再以空格替换该字符,最后再次左移光标
    
                    string--;
    
                }
    
            }
    
            else
    
            {
    
                *string++ = c;
    
                Uart_SendByte(c);
    
            }
    
        }
    
        *string='\0';
    
        Uart_SendByte('\n');
    
    }
    
    /********************************************************************
    
    // Function name	: Uart_SendByte
    
    // Description	    : 通过串口发送字符
    
    // Return type	: void
    
    // Argument         : int data:待发送字符
    
    *********************************************************************/
    
     
    
    void Uart_SendByte(int data)
    
    {
    
        if(whichUart==0)
    
        {
    
            if(data=='\n')
    
            {
    
                while(!(rUTRSTAT0 & 0x2));
    
    //            Delay(10);                 //because the slow response of hyper_terminal
    
                WrUTXH0('\r');
    
            }
    
            while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty.
    
    //        Delay(10);
    
            WrUTXH0(data);
    
        }
    
        else if(whichUart==1)
    
        {
    
            if(data=='\n')
    
            {
    
                while(!(rUTRSTAT1 & 0x2));
    
    //            Delay(10);                 //because the slow response of hyper_terminal
    
                rUTXH1 = '\r';
    
            }
    
            while(!(rUTRSTAT1 & 0x2));   //Wait until THR is empty.
    
    //        Delay(10);
    
            rUTXH1 = data;
    
        }   
    
        else if(whichUart==2)
    
        {
    
            if(data=='\n')
    
            {
    
                while(!(rUTRSTAT2 & 0x2));
    
    //            Delay(10);                 //because the slow response of hyper_terminal
    
                rUTXH2 = '\r';
    
            }
    
            while(!(rUTRSTAT2 & 0x2));   //Wait until THR is empty.
    
            Delay(10);
    
            rUTXH2 = data;
    
        }       
    
    }  
    
     
     

    组员总结:

    xx:

    这次实验的课题是串口通信,在这次实验中,我们通过编程实现了宿主机与目标机的字符串发送与接收,虽然实验现象看起来很简单,但是这种将数据通过宿主机处理然后返回到目标机来显示的方式很让我感到惊奇,而且通过这次实验,我也学到了ARM的串口工作原理,及其UART通信方式,总的来说这次实验还是很成功的,希望以后也能继续保持

     

    xxx:

    这次试验的课题是串口通信  串口通信的实验明显要比之前的实验要难了,代码的数量明显变多了 。头文件里有很多的代码,比之前的实验的代码要多的多。但是只要认真的去看代码,使用编译器自带的查找功能找到关键的函数,很容就看懂代码本身的意思。

     

    xxx:

    这次实验的课题是串口通信。串口通信的概念,即串口按位(bit)发送和接收字节。通过这次实验,我掌握了串口的使用方法,串口初始化,发送数据和接收数据,为以后的实验奠定了基础。通过有关书籍,我了解到嵌入式系统中串口是一个重要的资源,常用来做输入输出设备。

     

    xx:

      这次串口通信实验与第一次的实验相比,难度骤增,在实验过程中遇到了很多问题,第一次连接时,无论怎样都无法在超级终端上显示,硬件接口接触不良很是麻烦。后面修改代码通过调用关键函数完成了字符串的发送和字符删除。

     

    xx:

    UART(通用异步收发器)结构包括波特率发生器,发送器,接收器以及控制单元;有同时代表收发缓冲区状态的只读UTRSTAT寄存器,和其他收发数据,设计相应收发模式查询方式的寄存器;实验过程就是对发送数据格式,端口,寄存器等初始化,接收数据(接收缓冲区接收到数据),发送数据(发送缓冲区为空)的处理。越来越感受到纯编程和结合硬件编程的区别,体会到操作系统屏蔽硬件细节的伟大

     

    展开全文
  • 双单片机串口通信实验 一、实验目的 二、实验内容 三、实验步骤 四、C代码如下 五、实验结果 六、实验体会 一、实验目的 1、 掌握单片机串口通信的设计方法; 2、 了解双单片机通信的原理。 二、实验内容...

    双单片机串口通信实验

    一、实验目的

    二、实验内容

    三、实验步骤

    四、C代码如下

    五、实验结果

    六、实验体会


    一、实验目的

    1、 掌握单片机串口通信的设计方法;
    2、 了解双单片机通信的原理。

    二、实验内容

    编写发送方程序,接受方程序。

    三、实验步骤

    1 、打开 Keil 程序,执行菜单命令“ Project ” “New Project ”创建“双单片 机串口通信”项目,并选择单片机型号为 AT89C51
    2、执行菜单命令“ File ” “New”创建文件,输入源程序,保存为“双单片机 串口通信 .A51”。
    3、在“Project ”栏的 File 项目管理窗口中右击文件组, 选择“Add Files to Group ‘Source Group1 ’”将源程序“双单片机串口通信.A51”添加到项目中。
    4、执行菜单命令“ Project ” “Options for Target ‘Target 1 ’”, 在弹出的 对话框中选择“ Output ”选项卡,选中“ Greate HEX File ”。
    5、执行菜单命令“ Project ” “Build Target ”,编译源程序。如果编译成功,则在“ Output Window”窗口中显示没有错误,并创建了“双单片机串口通信 .HEX”文件。
    6、在 proteus 仿真平台上建立参考图系统,并将程序上载到虚拟芯片上运行。

    四、C代码如下

    //两个单片机通讯,使用中断法


    #include <reg51.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define key_port P1
    #define dis_port P2

    void main (void)
    {
        uchar key_in=0xff;
        SCON=0x50; //MODER1,REN=1;
        TMOD=0x20; //TIMER1 MODER2;
        TH1=0xf3;  //bode=2400
        TL1=0xf3;
        ET1=1;
        TR1=1;

        EA=1;
        ES=1;
        while(1)
        {        
            if (key_in != key_port)
                {
                    key_in = key_port;
                    SBUF=key_in;
                }
        }
    }

    void get_disp (void) interrupt 4 using 0
    {
        if (RI)            //如果是串口输入引起中断
                {
                    dis_port = SBUF;
                    RI=0;
                }
         else TI=0;        //否则就是串口输出引起的中断
    }

    五、实验结果

    六、实验体会

    通过本次实验,使得我掌握了单片机串口通信的设计方法;了解了双单片机通信的 原理,从而,对于以后的多单片机通信有一定的基础,知道了一些其中的必须的东西, 我想在以后做类似的多单片机通信时会有一定的帮助。在实验的过程中,可以说数码管显示实验是没有什么难度的,因为我在前面已经做过了这么一个实验,但是在设计程序的时候,要尽可能的先料及数码管动态显示的原理然后根据具体情况才能很好的了解如 何使用了;其次是编写代码时要加注释不然后续查错很困难;最后,此次实验“双单片 机通信”的是用书上汇编语言来编写的,需要对单片机的功能、原理、使用方法和步骤 等都要有很深的了解,虽然代码书上已经给出,只是输入程序的时候要仔细,千万千万不要犯一些低级错误,这样反而会得不偿失,到最后,浪费了大把的时间仍然不能把实验顺利完成! 也是通过本次实验,让我明白了在做实验时万万不可偷工减料,否则最后吃亏的仍然是自己在第一次开始的时候一定要将电路图画好,不然的话就算程序是对的也无法观察到正确的现象,得出正确的结果;做软件设计的候要特别认真的做好每一步,如果设计的程序很长,就很难在后期的调试中找到逻辑上的错误;做设计的时候要清楚的知道单片机各个引脚和端口的功能,如果不能理解,可以请教老师同学并且在每次实验中多积累积累经验,从而可以学到更多,虽然此次实验短暂而且难做,但是做完后返回去看看,这其中还是有诸多问题,比如说:自己不够细心、编写代码时粗心大意、运
    行时不小心、画电路原理图时没有画完整等等。我在以后的实验中一定会更加注意不让此类问题的发生!
    展开全文
  • 文章目录【实验目的】【实验原理】一、USART接口简介二、串口通信分类及原理三、硬件连接和USART库函数介绍四、软件流程图【实验环境】操作系统:设备简介:【实验步骤】一、配置工程环境二、开启时钟...
  • 基于STM32的UART串口通信实验 一 串口通信原理: 1.1 本实验实现串口助手发送数据然后回送在串口助手呈现出来。1.2 实验思路:看懂电路图,理解uart串口通信原理。1.3 开发环境 : MDK5 库函数版本开发 JLINK仿真 二...
  • USART 串口通信配置步骤在上面的介绍中,可能有的朋友很不理解,不过没有关系,下面我们讲解如何使用库函数对 USART 进行配置。这个也是在编写程序中必须要了解的。具体步骤如下:(USART 相关库函数在 stm32f10x_...
  • 先回顾上节课的串口配置步骤 首先看 void uart_init(u32 bound){ //1.首先可以看到这里的uart_init(u32 bound){} //可以看到这里参数以个波特率 usart.h这个文件中定义了 可以看到extern这个,指定了...
  • STM32基础实验③:串口通信

    千次阅读 2018-03-06 17:21:01
    简单串口通信实例 1、串口设置的一般步骤可以总结为如下几个步骤: 1) 串口时钟使能,GPIO时钟使能 2) 串口复位 3) GPIO端口模式设置 4) 串口参数初始化 5) 开启中断并且初始化NVIC(如果需要开启中断才...
  • 1-4 实验3 串口通信

    千次阅读 2013-10-14 10:10:41
    串口通信 1、实验内容:PC端串口调试助手向板子发送数据,板子接受到数据后,再把数据发送回给PC端串口调试助手 2、串口发送接受数据的基本步骤:初始化串口(设置波特率、中断等)、向缓冲区发送数据或者从接受缓冲...
  • STM32F1--串口通讯实验

    2019-02-19 10:55:31
    串口通讯实验串口通讯实验--通讯的基本概念通讯的基本概念串口通讯实验--USART介绍串口通讯简介USART 同步异步收发器USART的结构框图串口通讯实验--USART 的配置步骤串口实验通信控制程序 参考的网址:...
  • visual C++_Turbo C串口通信编程实践

    热门讨论 2010-07-30 09:14:24
    里面讲了MSComm控件 、 WinAPI 串口通信、CSerial类,例子很详实,每一步操作都有解释。作者是龚建伟,有一个个人主页www.gjwtech.com,讲串口通信的内容比较多,还行,大家可以先看看这个主页。 本书目录 第1章轻松...
  • STM32串口通信实验 1212 一.中断优先级设置步骤 1.先设置中断优先级分组 2.针对每个中断。设置对应的抢占优先级和响应优先级(抢占级高的可以打断低的;抢占级一样的,当两个中断同时发生的情况下,那个响应优先级高...
  • STM32串口通信

    2020-12-05 11:58:06
    目录一、实验环境二、实验目的三、步骤三、其它 基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式有什么差异? 基于寄存器点亮是通过参考手册的寄存器介绍图来编程,从而操作寄存器相应的位来实现引脚输入...
  • 4-STM32F1 串口通信-中断方式

    千次阅读 2018-01-22 15:44:42
    实验是在上个实验《STM32F1 串口通信-查询方式》的基础上做的,所以这里只总结增加的中断的部分,串口IO和串口初始化和上个实验一样。 增加的步骤 1,在主函数中进行中断分组 2,在使能串口前配置串口中断, 3,使...
  • 为解决特殊场合DSP程序升级困难的问题,以TMS320F28035为例,介绍了一种基于串口通信的适合于TMS320C2000系列DSP实现程序更新的在线升级方法。描述了该在线升级方法的基本思想和实现步骤,给出了关键部分的程序代码...
  • 实验步骤①利用指令来控制灯的亮灭,例如输入“open”让灯亮,输入“close”让灯灭。需要赋值文本:②首先判断是否有数据可以读,然后用赋值的方法对字符串进行读取,并打印:③当输入“open”让灯亮,输入“...
  • 配置环境二、Arduino IDE的串口通信1.实验环境2.代码:3.程序配置4.编译 一、Ardunio IDE的安装及配置 1.安装JDK 由于Arduino IDE依赖JAVA开发环境,所以需要提前安装JDK。 官方地址 步骤如下: 2.下载Ardunio ...
  • 书名:《Visual C++串口通信技术详解》(机械工业出版社.李景峰.杨丽娜.潘恒) PDF格式扫描版,全书分为16章,共368页。2010年6月出版。 内容简介 本书介绍如何利用Visual C++集成开发环境进行串口通信程序开发。书...
  • 并行通信串行通信常见的串行通信接口二、 STM32串口通信基础UART 和 USART三、实验部分实验步骤总结 前言 本文参考了网上的博文,并加以归纳总结,帮助新手从入门到放弃 。 提示:以下是本篇文章正文内容 一、串口...
  • 树莓派利用串口进行通信

    万次阅读 2018-12-21 16:19:53
    树莓派串口通信 我用的是树莓派3b+型号,网上各种各样的修改方式来使得树莓派的串口可以工作,过于混乱,还有的教程甚至会被树莓派系统搞崩溃,尤其是树莓派实验室那里的中文教程,是错误的,按照那个来就直接系统...
  • stm32--第一个串口通信程序

    千次阅读 2016-07-17 13:35:03
    功能:编写一个程序实现开发板与电脑通信,通过PC机上的串口调试助手发送Hello STM32F429给开发板,开发板中断接收数据,然后将接收到的数据发送给PC机的串口调试助手。 实验开发板:stm32f429 硬件设计: ...
  • STM32F0单片机串口实验

    2020-08-16 16:28:25
    STM32F0单片机实验:...3、实验步骤 1)对使用的端口(包括串口,普通GPIO口)进行初始化,其中串口初始化的内容主要包括时钟配置、使能。 主要通过三个结构体来实现USART_InitTypeDef,NVIC_InitTypeDef, GPIO_Init
  • mcu外部的重要接口,也是软件调试的重要调试方式,不管是调试串口,还是通信串口,原理都是一样,这次我们将使用串口1来接收pc发出的数据,再将数据发回给pc,我们使用的是正点原子板载usb串口。 接下来我们要进行...
  • 第四章 stm32 cubemx 串口中断实验以及proteus仿真 文章目录第四章 stm32 cubemx 串口中断实验以及proteus仿真前言一...本章将实现如下功能:STM32F103 通过串口实现板子之间的通信,利用通信来实现板子间的控制,如果S
  • STM32F103学习笔记(四) 串口实验

    千次阅读 2015-01-22 19:57:55
    串口通信,首先进行串口的设置:  串口设置的一般步骤可以总结为如下几个步骤: 1) 串口时钟使能, GPIO 时钟使能 2) 串口复位 3) GPIO 端口模式设置 4) 串口参数初始化 5) 开启中断并且初始化 NVIC(如果...
  • 串口调试助手,适合通信工程,电子信息工程等专业的同学学习使用,包含详细代码注释及实验步骤串口调试工具可设置波特率,传输协议等,
  • 3、实验步骤 3.1、使用 STM32CubeMX 新建项目工程 3.2、编写双串口代码 3.3、配置烧写参数 3.4、烧录程序 1、实验目的 了解STM32L432KC UART1和UART2的原理及特性; 学习STM32CubeMX新建双串口工程的方法; ...

空空如也

空空如也

1 2 3 4
收藏数 78
精华内容 31
关键字:

串口通信实验步骤