dtcms插件 OpenCV4 gps gitee codeigniter symfony xpath video input Pure CSS vue绑定点击事件 bootstrap后台管理系统模板 系统后台模板 angularjs视频教程 jquery each list获取最后一个元素 base64转16进制 mysql删除一列 oracle添加索引 coreldraw入门学习 bootstrap居中对齐 matlab求向量的模 python创建数据库 python语言编程 python打开文件夹 python传递参数 java如何连接mysql java安装教程 怎么安装linux系统 超级煎蛋卷 枪神传说辅助 如何强行退出小米账号 js格式化时间 快捷精灵 netreflector ip地址转换器 博途v14安装教程 掌门一对一下载 办公室复印机使用方法 tableau下载
当前位置: 首页 > 学习教程  > 

物联网之LoRa开发与应用五(串口透传开发)

2020/10/16 17:46:14 文章标签: lora开发

LoRa串口透传系统设计 内容概要: 1、串口透传系统设计需求 2、串口透传系统通信机制 3、串口透传系统业务流程 串口透传系统设计需求: 1、将LoRa终端定义成两种角色:Master(主机)和Slave(从机&#xf…

LoRa串口透传系统设计

内容概要

1、串口透传系统设计需求

2、串口透传系统通信机制

3、串口透传系统业务流程

串口透传系统设计需求

1、将LoRa终端定义成两种角色:Master(主机)和Slave(从机)

2、一个模块发送任意字节长度(小于128Byte)数据,另一模块都可以接收到

3、PC机上通过串口调试助手实现接收和发送

4、终端在LCD屏幕上显示终端类型及收发数据包个数

串口透传系统通信机制

串口透传业务流程-初始化

串口透传业务流程-主程序

串口透传业务流程-LCD任务

串口透传业务流程-串口接收任务

串口透传业务流程-无线任务

LoRa串口透传系统功能开发

内容概要:

1、串口功能开发

2、LCD功能开发

3、无线收发功能开发

串口功能接口:(这里介绍了相关函数和相关代码,里面使用到的一些变量在下面串口数据结构中会有说明)

​//启动串口1,使能串口空闲中断 。设置为空闲中断模式可以在整包之后才进行数据的收发,然后产生中断,避免重复单个数据的收发(减小开销)
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//注意:使能空闲中断后,不管有没有接收数据,会先触发一次中断,发送一次数据 
  HAL_UART_Receive_DMA(&huart1,a_Usart1_RxBuffer,RXLENGHT); //打开DMA接收,串口空闲中断模式配合DMA进行数据的接收
 (以上两行代码功能:将uart1接收到的数据通过DMA传递给a_Usart1_RxBuffer,然后产生串口空闲中断,在中断中做进一步处理)

void USART1_IRQHandler(void)
{
    /* USER CODE BEGIN USART1_IRQn 0 */
  uint32_t temp;
  
  //判断是否产生空闲中断
  if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)  != RESET )
  {
    //清除中断标志
   __HAL_UART_CLEAR_IDLEFLAG(&huart1);
   temp = huart1.Instance->ISR;  //读取寄存器的值
   temp = huart1.Instance->RDR;  //读取寄存器的值
   HAL_UART_DMAStop(&huart1);  //停用DMA  关键点1:以上两行代码用于清除DMA的接收中断(只需要读取一次ISR和RDR寄存器的值)
   temp  = hdma_usart1_rx.Instance->CNDTR;             
   UsartType1.Usart_rx_len =  RXLENGHT - temp; /*CNDTR为DMA通道接收数据的计数器(注意是一个递减计数器,
                       所以需要将DMA的缓存区的总长度减去该计数器的值才是DMA通道接收数据的长度)*/
   HAL_UART_RxCpltCallback(&huart1); //调用回调函数,在回调函数中具体实现数据的接收 关键点2
  }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{ 
  uint8_t Old_len = 0;
  
  if(UartHandle->Instance == USART1)//判断是否为USART1中断
  {  
    Old_len = strlen(UsartType1.usartDMA_rxBuf);//读取发送缓冲区UsartType1.usartDMA_rxBuf的长度(如果为0则表示没有数据)
    if(0 != Old_len) /*如果发送缓冲区中还有数据,则将DMA中接收缓冲区a_Usart1_RxBuffer的数据拷贝到发送缓冲区的末尾
                              (不覆盖发送缓冲区前面的数据)*/
    {
      memcpy(&UsartType1.usartDMA_rxBuf[Old_len],a_Usart1_RxBuffer,UsartType1.Usart_rx_len);
      Old_len=0;
    }
    else  /*如果发送缓冲区UsartType1.usartDMA_rxBuf中没有数据,则直接将DMA中接收缓冲区a_Usart1_RxBuffer的数据
                      拷贝到发送缓冲区的起始位置*/
      memcpy(UsartType1.usartDMA_rxBuf,a_Usart1_RxBuffer,UsartType1.Usart_rx_len);
//      UsartxSendData_DMA(&huart1,a_Usart2_RxBuffer,UsartType2.Usart_rx_len);
      memset(a_Usart1_RxBuffer,0,UsartType1.Usart_rx_len);//清空DMA中接收缓冲区a_Usart1_RxBuffer的数据
      HAL_UART_Receive_DMA(&huart1,a_Usart1_RxBuffer,RXLENGHT);//继续打开DMA接收
      UsartType1.receive_flag =1; //接收标识位,置1表示发送缓冲区中有新的数据,提醒相关函数将数据发送出去
  }
}

//**********************************//
//
//函数名称:UartDmaGet   
//
//函数描述:串口数据获取   
//
//函数参数:   无
//
//返回值:     无
//
//创建者: 
//*******************************//

void UartDmaGet(void) //串口接收任务处理函数
{
  if(UsartType1.receive_flag == 1)//如果发送缓冲区中有新的数据,则将其发送给sx1278
  {
    //串口接收到的数据原封发给SX1278,sx1278通过无线将数据发送出去
    Radio->SetTxPacket(UsartType1.usartDMA_rxBuf, UsartType1.Usart_rx_len);
    
    memset(UsartType1.usartDMA_rxBuf,0,UsartType1.Usart_rx_len);
    UsartType1.receive_flag = 0; //接收数据标志清零
  }
}

串口数据结构

上述代码中使用到的相关变量的定义如下:

#define RXLENGHT  128
#define RECEIVELEN 2048
#define USART_DMA_SENDING       1//发送未完成
#define USART_DMA_SENDOVER      0//发送完成

typedef struct
{
  uint8_t receive_flag ;//空闲接收标记
  uint8_t dmaSend_flag ;//发送完成标记
  uint16_t Usart_rx_len;//接收长度
  uint8_t usartDMA_rxBuf[RECEIVELEN];//无线发送缓存
}USART_RECEIVETYPE;

extern USART_RECEIVETYPE UsartType1;
extern USART_RECEIVETYPE UsartType2;
//
局部变量
//extern uint8_t g_Usart1_RxBuffer[RXLENGHT]; 
//extern uint8_t g_Usart2_RxBuffer[RXLENGHT]; 
全局变量
extern uint8_t a_Usart1_RxBuffer[RXLENGHT]; //DMA接收缓存
//extern uint8_t a_Usart2_RxBuffer[RXLENGHT]; 

LCD功能开发:略

 

无线收发功能开发:(略)

//**********************************//
//
//函数名称:  RxDataPacketNum 
//
//函数描述:  接收数据包计数 
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void RxDataPacketNum(void)
{
  if(EnableMaster == true)
    Master_RxNumber++;
  else
    Slave_RxNumber++;
}
//**********************************//
//
//函数名称:   TxDataPacketNum
//
//函数描述:   发送数据包计数
//
//函数参数:  无 
//
//返回值:     无
//
//创建者:     
//*******************************//

void TxDataPacketNum(void)
{
  if(EnableMaster == true)
    Master_TxNumber++;
  else
    Slave_TxNumber++;
}

最后给出main.c文件的全部代码:

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f0xx_hal.h"
#include "adc.h"
#include "dma.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include <stdio.h>
#include <string.h>
#include "lcd.h"
#include "led.h"
    
#include "logo.h"


//sx1278
#include "platform.h"
#include "radio.h"
#include "sx1276-Hal.h"
#include "sx1276-LoRa.h"
#include "sx1276-LoRaMisc.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

#define BUFFER_SIZE 128

static uint16_t BufferSize = BUFFER_SIZE;
static uint8_t Buffer[BUFFER_SIZE];

#if defined(MASTER)

static uint8_t EnableMaster = true;

#elif defined(SLAVE)

static uint8_t EnableMaster = false;

#endif


tRadioDriver *Radio = NULL;

static uint32_t Master_RxNumber = 0;
static uint32_t Master_TxNumber = 0;

static uint32_t Slave_RxNumber = 0;
static uint32_t Slave_TxNumber = 0;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
//**********************************//
//
//函数名称:UartDmaGet   
//
//函数描述:串口数据获取   
//
//函数参数:   无
//
//返回值:     无
//
//创建者: 
//*******************************//

void UartDmaGet(void) //串口接收任务处理函数
{
  if(UsartType1.receive_flag == 1)//如果发送缓冲区中有新的数据,则将其发送给sx1278
  {

    //串口接收到的数据原封发给SX1278,sx1278通过无线将数据发送出去
    Radio->SetTxPacket(UsartType1.usartDMA_rxBuf, UsartType1.Usart_rx_len);
    
    memset(UsartType1.usartDMA_rxBuf,0,UsartType1.Usart_rx_len);
    UsartType1.receive_flag = 0; //接收数据标志清零,
  }
}

//**********************************//
//
//函数名称:  RxDataPacketNum 
//
//函数描述:  接收数据包计数 
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void RxDataPacketNum(void)
{
  if(EnableMaster == true)
    Master_RxNumber++;
  else
    Slave_RxNumber++;
}
//**********************************//
//
//函数名称:   TxDataPacketNum
//
//函数描述:   发送数据包计数
//
//函数参数:  无 
//
//返回值:     无
//
//创建者:     
//*******************************//

void TxDataPacketNum(void)
{
  if(EnableMaster == true)
    Master_TxNumber++;
  else
    Slave_TxNumber++;
}
//**********************************//
//
//函数名称:  Sx127xDataGet 
//
//函数描述:   读取sx127x射频射频数据
//
//函数参数:   无
//
//返回值:     无
//
//创建者:    
//*******************************//

void Sx127xDataGet(void)
{
  switch( Radio->Process( ) )
  {
  case RF_RX_TIMEOUT:
    printf("RF_RX_TIMEOUT\n");
    break;
  case RF_RX_DONE:
    Radio->GetRxPacket( Buffer, ( uint16_t* )&BufferSize );
    if(EnableMaster == true)
      printf("master Rx__%s,__,%d,%d\n",Buffer,strlen((char*)Buffer),BufferSize);
    else
      printf("slave Rx__%s,__,%d,%d\n",Buffer,strlen((char*)Buffer),BufferSize);      
    if( BufferSize > 0 )//&& (BufferSize == strlen((char*)Buffer)))
    {
      //接收数据闪烁
      LedBlink( LED_RX );
      //计算接收数据的个数
      RxDataPacketNum();

      //清空sx127x接收缓冲区
      memset(Buffer,0,BufferSize );
    }            
    break;
  case RF_TX_DONE:
    //发送闪烁
    LedBlink( LED_TX );
    //计算发送数据的个数
    TxDataPacketNum();
    Radio->StartRx();//打开接收模式
    break;
  case RF_TX_TIMEOUT:
    printf("RF_TX_TIMEOUT\n");
    break; 
  default:
    break;
  }
}


//**********************************//
//
//函数名称:MLCD_Show   
//
//函数描述:LoRa主机屏幕显示数据   
//
//函数参数:无   
//
//返回值:无  
//
//创建者:     
//*******************************//

void MLCD_Show(void)
{
  
  uint8_t str[20] = {0};
  
  LCD_GPIO_Init();
  
  
  
  sprintf((char*)str,"%d",Master_RxNumber);
  Gui_DrawFont_GBK16(64,48,BLACK,YELLOW,str);
  
  memset((char*)str,0,strlen((char*)str));
  
  
  sprintf((char*)str,"%d",Master_TxNumber);
  Gui_DrawFont_GBK16(64,64,BLACK,YELLOW,str);
  
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
}
//**********************************//
//
//函数名称:SLCD_Show   
//
//函数描述:LoRa从机屏幕显示数据    
//
//函数参数:无   
//
//返回值:  无 
//
//创建者:    
//*******************************//

void SLCD_Show(void)
{


  uint8_t str[20] = {0};
  
  LCD_GPIO_Init();
  
  sprintf((char*)str,"%d",Slave_RxNumber);
  Gui_DrawFont_GBK16(64,48,BLACK,YELLOW,str);
  
  memset((char*)str,0,strlen((char*)str));
  
  sprintf((char*)str,"%d",Slave_TxNumber);
  Gui_DrawFont_GBK16(64,64,BLACK,YELLOW,str);
  
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
  
}



/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */
  
  uint8_t RegVersion = 0;

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC_Init();
  MX_USART1_UART_Init();
  MX_SPI1_Init();
  
  Lcd_Init();
  showimage(gImage_logo);
  HAL_Delay(500);
  Lcd_Clear(YELLOW);

  Gui_DrawFont_GBK16(0,0,RED,GREEN,"  LoRa Topology  ");
#if defined (SLAVE)  
  Gui_DrawFont_GBK16(0,16,RED,GREEN,"     Slave      ");
#elif defined (MASTER)
  Gui_DrawFont_GBK16(0,16,RED,GREEN,"     Master     ");
#endif
  Gui_DrawFont_GBK16(0,32,BLACK,YELLOW,"SSID:");
  Gui_DrawFont_GBK16(64,32,BLACK,YELLOW,"30");
  
  Gui_DrawFont_GBK16(0,48,BLACK,YELLOW,"RX:");
  Gui_DrawFont_GBK16(0,64,BLACK,YELLOW,"TX:");
  
  
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
  
  
  //启动串口1,使能串口空闲中断  
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); 
  HAL_UART_Receive_DMA(&huart1,a_Usart1_RxBuffer,RXLENGHT); 

  SX1276Read( REG_LR_VERSION, &RegVersion );
  
  if(RegVersion != 0x12)
  {
    printf("LoRa read Error!\r\n");
    printf("LoRa RegVersion = %d!\r\n",RegVersion);
  
  }
  else
  {
    printf("LoRa read Ok!\r\n");
    printf("LoRa RegVersion = %d!\r\n",RegVersion);
  
  
  
  }
  
  //读到版本号后,关闭3种灯
  LedOff(LED_RX);
  LedOff(LED_TX);
  LedOff(LED_NT);
  
  Radio = RadioDriverInit();
  
  Radio->Init();
  
  
  printf("systerm init ok!");
  
  
  Radio->StartRx( );//打开接收模式                    


  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    
    UartDmaGet();//串口接收任务处理函数
    
    Sx127xDataGet();//读取sx127x射频射频数据
    if(EnableMaster == true)
    {
     MLCD_Show();

    }
    else
    {
      SLCD_Show();
    }

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSI14State = RCC_HSI14_ON;
  RCC_OscInitStruct.HSI14CalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void _Error_Handler(char * file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1) 
  {
  }
  /* USER CODE END Error_Handler_Debug */ 
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif


int fputc(int ch,FILE *f)
{
  
  while((USART1->ISR&0X40) == 0);
  
  USART1->TDR = (uint8_t)ch;
  
  return ch;
  
}


/**
  * @}
  */ 

/**
  * @}
*/ 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

 


本文链接: http://www.dtmao.cc/news_show_300118.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?