基于UCOSII的RS485通信(STM32F107)

2023-05-16

一、实现效果

        基于ucosii实时操作系统的RS485通信,采用USART + DMA进行收发,

 二、开发环境

  • 开发工具:KEIL V5
  • 开发板: STM32f107RC
  • 采用方式:USART + DMA
  • 使用系统:UCOSII

三、RS485部分原理

        在RS-485通讯网络中,节点中的串口控制器使用RXTX信号线连接到收发器上,而收发器通过差分线连接到网络总线,串口控制器与收发器之间一般使用TTL信号传输,收发器与总线则使用差分信号来传输。

        发送数据时,串口控制器的TX信号经过收发器转换成差分信号传输到总线上,

        而接收数据时,收发器把总线上的差分信号转化成TTL信号通过RX引脚传输到串口控制器中。

        MCU管脚输出TTL电平,TTL电平的意思是,当MCU管脚输出0电平时,一般情况下电压是0V,当MCU管脚输出1电平时,电压是5V。因TTL电平的是由一条信号线,一条地线产生,信号线上的干扰信号会跟随有效信号传送到接收端,使得有效信号受到干扰,485通讯实际上是把MCU出来的TTL电平通过硬件层的一个转换器芯片进行转换

        RS-485通讯网络的最大传输距离可达1200米,总线上可挂载128个通讯节点,而由于RS-485网络只有一对差分信号线,它使用差分信号来表达逻辑,AB两线间的电压差为-6V~-2V时表示逻辑1,当电压差为+2V~+6V表示逻辑0,在同一时刻只能表达一个信号,所以它的通讯是半双工形式的。

        在单个实验板中,作为串口控制器的STM32USART外设引出TXRX两个引脚与RS-485收发器MAX485相连,收发器使用它的AB引脚连接到RS-485总线网络中。为了方便使用,我们每个实验板引出的AB之间都连接了1120欧的电阻作为RS-485总线的端电阻,所以要注意如果要把实验板作为一个普通节点连接到现有的RS-485总线时,是不应添加该电阻的

        MAX485芯片中有"RE"和"DE"两个引脚,用于控制485芯片的收发工作状态的,当RE引脚为低电平时,485芯片处于接收状态,当DE引脚为高电平时芯片处于发送状态。实验板中使用了STM32PD11直接连接到这两个引脚上,所以通过控制PD11的输出电平即可控制485的收发状态。

 实验板之间AA连接,BB连接即可

四、配置操作

 建立了5个任务

  任务名                                                 优先级
            APP_TASK_START_PRIO              2            主任务              
            Task_Com4_PRIO                           4            COM4通信任务
          
         当然还包含了系统任务:
            OS_TaskIdle                  空闲任务-----------------优先级最低
            OS_TaskStat                  统计运行时间的任务-------优先级次低 

 4.1 主任务建立

 //建立主任务, 优先级最高  建立这个任务另外一个用途是为了以后使用统计任务
os_err = OSTaskCreate((void (*) (void *)) App_TaskStart, (void *) 0,   //指向任务代码的指针                                 
                                  (void *) 0,    //任务开始执行时,传递给任务的参数的指针                                       
               (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], //分配给任务的堆栈的栈顶指针   从顶向下递减   
               (INT8U) APP_TASK_START_PRIO);    //分配给任务的优先级  
static  void App_TaskStart(void* p_arg) 
{
   (void) p_arg
 
   //使能ucos 的统计任务
   
#if (OS_TASK_STAT_EN > 0)
    //----统计任务初始化函数 
    OSStatInit();                                      /* Determine CPU capacity.   */                         
 #endif
   
   //建立其他的任务  
   App_TaskCreate();

   while (1)
   {       
	  //1秒一次循环
      OSTimeDlyHMSM(0, 0,1, 0);
    }
 }

4.2 其他任务建立

static  void App_TaskCreate(void)
  {
     //CPU_INT08U os_err;
		
    //Com1_SEM=OSSemCreate(1);            //建立串口4中断的信号量
    Com4_MBOX = OSMboxCreate((void *) 0);             //建立串口4中断的消息邮箱
     
     //串口4接收及发送任务---------------------------------------------------------    
     OSTaskCreateExt(Task_Com4,                    //指向任务代码的指针
                        (void *)0,                 //任务开始执行时,传递给任务的参数的指针
                     (OS_STK *)&Task_Com4Stk[Task_Com4_STK_SIZE-1],//分配给任务的堆栈的栈顶指针   从顶向下递减
                     Task_Com4_PRIO,               //分配给任务的优先级
					 Task_Com4_PRIO,               //预备给以后版本的特殊标识符,在现行版本同任务优先级
                     (OS_STK *)&Task_Com4Stk[0],   //指向任务堆栈栈底的指针,用于堆栈的检验
                     Task_Com4_STK_SIZE,           //指定堆栈的容量,用于堆栈的检验
                     (void *)0,                   //指向用户附加的数据域的指针,用来扩展任务的任务控制块
				     OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //选项,指定是否允许堆栈检验,是否将堆栈清0,任务是否要进行浮点运算等等。 
}

4.2.1 建立子任务——串口通信的任务

串口通信的任务:这里采用消息邮箱进行消息传递,

  • 在建立其他任务App_TaskCreate(void)的开始就首先建立串口的消息邮箱:Com4_MBOX=OSMboxCreate((void *) 0);
  • 然后在串口通信的任务中进入循环后就一直等待消息邮箱的信息(第8行),如果没有消息过来就一直等待,在此期间其他任务可以进行,一旦有消息发送过来,由于串口通信的优先级较高,就能很快响应,根据收到的消息msg来自定义。
  • 这里因为串口接收要用到中断,所以下面就说说串口通信的接收中断部分。
static  void Task_Com4(void *p_arg)
{    
     INT8U err;
		 int i;
    unsigned char * msg;
     (void)p_arg;                        
     while(1)
	{
          
       //OSSemPend(Com1_SEM,0,&err);          //等待串口接收指令成功的信号量
       msg=(unsigned char *)OSMboxPend(Com4_MBOX, 0,&err);         //等待串口接收指令成功的邮箱信息
		
        //输出邮箱信息的前10个数据
      if(msg != NULL)
	  {
			for(i = 0; i < 2; i++)
			{
				G_u8Usart1SendBuf[i] = 0x10;
			}
					
			USART_DMA_SendStart(DMA2_Channel5, 2);
					
			memcpy(G_u8Usart1SendBuf, msg, 10);
					
			USART_DMA_SendStart(DMA2_Channel5, 10);
		}

	    //DealWith_Data(pfifo); //处理数据
    } 
 }

        以下是串口中断函数,接收串口数据,当发现是完整的帧时,就调用OSMboxPost(Com4_MBOX,(void *)&msg);发送一个邮箱消息,进而那边的串口任务从挂起到唤醒,执行相应的过程。

使用ringbuffer实现任意数据类型的FIFO处理接收数据,可以参考:stm32f0串口 DMA 空闲中断接收——基于HAL库(代码篇)_噗噗bug博客-CSDN博客

void UART4_IRQHandler(void)
{
  uint16_t t;
	unsigned int i;
	unsigned char msg[50];
	OS_CPU_SR  cpu_sr;
	
	OS_ENTER_CRITICAL()     //保存全局中断标志,关总中断/
	OSIntNesting++;
	
	OS_EXIT_CRITICAL();  //恢复全局中断标志
	
	if(USART_GetITStatus(UART4,USART_IT_IDLE) == SET)          //检查中断是否发生
	{	
		RS485_TX_EN = 0;   
		
		DMA_Cmd(DMA2_Channel3,DISABLE);                         //关闭DMA传输
        DMA_ClearFlag( DMA2_FLAG_TC3 );  
		t = DMA_GetCurrDataCounter(DMA2_Channel3);              //获取剩余数量
		
		//FIFO_Add(pfifo, G_u8Usart1RecvBuf, UART4_RECV_MAXLEN - t); //fifo数据保存
		
		memcpy(msg, G_u8Usart1RecvBuf, UART4_RECV_MAXLEN - t);
	    OSMboxPost(Com4_MBOX,(void *)&msg);
		
		DMA_SetCurrDataCounter(DMA2_Channel3,UART4_RECV_MAXLEN);   //重新设置传输的数量
		
		 
		DMA_Cmd(DMA2_Channel3,ENABLE);                      //开启DMA传输
		USART_ReceiveData(UART4);                           //读一次数据,不然会一直进中断
		USART_ClearFlag(UART4,USART_FLAG_IDLE);             //清除串口中断标志
	}
	
	OSIntExit();
}

4.3 硬件初始化部分 

void BSP_Init(void)
{
 
  /* NVIC configuration */
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
   RS485_Config();
   uart_init(9600);
   delay_init();       //延迟函数初始化
}

 4.4 RS485发送函数

注意:在485芯片的通信中,尤其要注意对485控制端DE的软件编程。为了可靠工作,在485总线状态切换时需要做适当延时,再进行数据收发。具体的做法是

     在数据发送状态下,   先将控制端置“1”,延时1ms左右的时间,在发送有效的数据,一包数据发送结束后再延时1ms后,将控制端置“0”,这样处理会使总线在状态切换时,有一个稳定的工作过程。代码中延迟10ms(参考:https://blog.csdn.net/yx_l128125/article/details/7914102)

#define RS485_TX_EN  PAout(15)   设置RS485 mode控制, RX:0, TX:1

void USART_DMA_SendStart(DMA_Channel_TypeDef *DMA_Streamx, u16 m_u16SendCnt)  
{    
	USART_DMACmd(UART4, USART_DMAReq_Tx, ENABLE);
    RS485_TX_EN = 1;
	delay_ms(10);	//延迟
    DMA_Cmd(DMA_Streamx, DISABLE);   
	delay_ms(10);	//延迟	
    DMA_SetCurrDataCounter(DMA_Streamx, m_u16SendCnt);  
    DMA_Cmd(DMA_Streamx, ENABLE);                      

	while(1)
	{
		if(DMA_GetFlagStatus(DMA2_FLAG_TC5)!=RESET)//µÈ´ýͨµÀ5´«ÊäÍê³É
		{
			DMA_ClearFlag(DMA2_FLAG_TC5);//Çå³ýͨµÀ5´«ÊäÍê³É±êÖ¾
			break; 
		 }
	}		
		
	delay_ms(10);	//延迟
	RS485_TX_EN=0;   
} 

4.5 主函数

int main(void)
{	
    unsigned  char os_err;
	
	OSInit();  
    //硬件初始化
    BSP_Init();    
  
   // FIFO 环型处理数据初始化
	pfifo = &fifo;
	FIFO_Init(pfifo, aRxFIFOBuffer, sizeof(uint8_t), RXFIFOBUFFERSIZE);
	
    OSInit();
	
    //先发送一段数据,可屏蔽
	for(i = 0; i < 50; i++)
	{
		G_u8Usart1SendBuf[i] = 0x10 + i;
	}
	USART_DMA_SendStart(DMA2_Channel5, 50);
	
	 os_err = OSTaskCreate((void (*) (void *)) App_TaskStart, (void *) 0,                    //指向任务代码的指针                         (void *) 0,                                           //任务开始执行时,传递给任务的参数的指针
               (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],    //分配给任务的堆栈的栈顶指针   从顶向下递减
               (INT8U) APP_TASK_START_PRIO);    //分配给任务的优先级 
	
    OSTimeSet(0);
    OSStart();      /* Start multitasking*/
}

五、运行串口调试

 参考:[stm32][ucos] 1、基于ucos操作系统的LED闪烁、串口通信简单例程 - beautifulzzzz - 博客园

stm32f0串口 DMA 空闲中断接收——基于HAL库(代码篇)_噗噗bug博客-CSDN博客

代码:

https://download.csdn.net/download/qq_41070511/24419255

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于UCOSII的RS485通信(STM32F107) 的相关文章

  • UCOSII中的任务切换原理介绍

    1 多任务的引入 之所以引入多任务 xff0c 主要在于提高程序运行的效率 多任务的过程 xff0c 能够有效地发挥交换式任务的运作效率 类似的 xff0c 由于一个任务里面也有瓶颈的地方 xff0c 为了把瓶颈的地方抠出来 xff0c 让
  • UCOSII学习---五、任务通信之信号量

    一 xff1a 信号量的理解 xff1a 信号量的本质是数据操作锁 xff0c 它本身不具有数据交换的功能 xff0c 而是通过控制其他的通信资源 xff08 文件 xff0c 外部设备 xff09 来实现进程间通信 xff0c 它本身只是
  • stm32 ucosii消息队列 串口_UC/OSII消息队列、信号量集和软件定时器

    UCOSII消息队列 信号量集和软件定时器简介 上一章 xff0c 我们介绍了信号量和邮箱的使用 xff0c 本章我们介绍比较复杂消息队列 信号量集以及软件定时器的使用 消息队列 使用消息队列可以在任务之间传递多条消息 消息队列由三个部分组
  • UCOSII-消息邮箱与消息队列

    文章目录 一 事件控制块及事件处理函数1 等待任务列表2 事件控制块的结构3 操作事件控制块的函数4 空事件控制块列表 二 消息邮箱1 消息邮箱介绍2 消息邮箱操作步骤 三 消息队列1 消息指针数组2 队列控制块3 消息队列的操作流程 四
  • 485无线通信/数传模块_zigbee模块_RS485转ZigBee_顺舟智能

    一 概述 顺舟智能 SZ02系列 ZigBee无线串口通信设备 xff08 485无线通信 数传设备 xff09 xff0c 采用了加强型的ZigBee无线技术 xff0c 集成了符合 ZIGBEE协议的射频收发器和微处理器 xff0c 符
  • 一文彻底搞懂嵌入式中UART、RS232、RS485、CAN协议

    一文彻底搞懂嵌入式中UART RS232 RS485 CAN协议 之前分享过一些使用UART RS232 RS485 CAN协议进行传感器数据读取 伺服电机控制的文章 xff0c 但这些协议之间到底有什么不同 xff0c 工作原理又到底是什
  • STM32F107的串口通讯总结

    STM32F107的串口通讯总结 STM32F107 的串口通讯总结 1 STM32 的一般规律 xff0c 首先要使用串口必先使能串口时钟 xff0c 比如串口1 xff1a RCC APB2PeriphClockCmd RCC APB2
  • STM32F107的通用定时器中断实验总结

    1 STM32F107 的通用定时器是指 xff1a TIM2 TIM3 TIM4 TIM5 STM32F107 的高级定时器是指 xff1a TIM1 TIM8 STM32F107 的基本定时器是指 xff1a TIM6 TIM7 2 S
  • UCOSii中的信号量

    任务间简单通个信 xff0c A告诉B你LED亮一下 这种问题可以用信号量来处理 xff0c UCOSii中关于信号量的函数也就八个 xff0c 今天简单总结下 函数列表 CREATE A SEMAPHORE Description Thi
  • STM32串口/RS232/RS485

    1 串口引脚 xff0c 如果是异步通讯将UART CLK共地即可 xff0c 如果同步需要时钟 a UART RX 数据接收引脚 b UART TX 数据发送引脚 c UART CLK 时钟引脚 2 UART描述 为全双工 xff0c 异
  • 13_STM32Cubeide开发_RS485总线驱动

    一 485总线和硬件电路 典型的串行通讯标准是RS232和RS485 xff0c 它们定义了电压 阻抗等 xff0c 但不对软件协议给予定义 RS 485总线标准规定了总线接口的电气特性标准即对于2个逻辑状态的定义 xff1a 正电平在 4
  • ucosII的书籍

  • 串口485接法图_rs485接口接线方法

    展开全部 RS485采用差分信号负逻辑 xff0c 43 2V xff5e 43 6V表示 0 xff0c 6V xff5e 2V表示 1 62616964757a686964616fe4b893e5b19e31333365643661RS
  • Jetson TX2——串口的使用(TTL-RS485)

    Jetson TX2之串口的使用 xff08 TTL RS485 xff09 TX2串口设备 TX2 有5个 UARTs 到主连接器 其中UART3 用于 WLAN BT 有关 UARTs 的典型任务 请参见下表 查看可用串口设备 xff1
  • STM32的串口硬件流控(RS232/RS485)

    流控的概念源于 RS232 这个标准 xff0c 在 RS232 标准里面包含了串口 流控的定义 RS232 中的 RS 是Recommend Standard 的缩写 xff0c 即 推荐标准 之意 xff0c 它并不像 IEEE 128
  • RS485接线方式小科普

    欢迎来到东用知识小课堂 xff01 RS 485采用平衡发送和差分接收方式实现通信 xff1a 发送端将串行口的ttl电平信号转换成差分信号a xff0c b两路输出 xff0c 经过线缆传输之后在接收端将差分信号还原成ttl电平信号 RS
  • RS485接收数据后发送乱码

    序 最近调块板子上面有几路485 xff0c 控制芯片STM32F407VE 转换芯片ADM2587 xff0c 使用485转换器连接电脑 xff0c 发现串口助手向板子发送数据后会收到乱码 xff0c 经软硬件联合调试排除bug 一 问题
  • RS-485详解(一)

    RS 485是美国电子工业协会 EIA 在1983年批准了一个新的平衡传输标准 balanced transmission standard EIA一开始将RS Recommended Standard 做为标准的前缀 不过后来为了便于识别
  • uCOSii中的互斥信号量

    uCOSii中的互斥信号量 一 互斥型信号量项管理 MUTUAL EXCLUSION SEMAPHORE MANAGEMENT OSMutexAccept 无条件等待地获取互斥型信号量 OSMutexCreate 建立并初始化一个互斥型信号
  • Microchip PIC 的 Modbus 堆栈

    有人可以建议为 Microchip PIC18 处理器实现 Modbus RTU 从站的开源实现吗 我正在寻找 RS 232 RS 485 的 Modbus RTU 实现 但 Modbus TCP IP 实现也将受到欢迎 我已经为 PIC1

随机推荐