电力电子技术
直播中

李伟嘉

7年用户 177经验值
私信 关注
[问答]

MM32F013x上实现UART单线半双工的功能应用

本文将介绍在MM32F013x上实现UART单线半双工的功能应用。

回帖(3)

郝汉

2021-1-22 15:57:08
  UART单线半双工简介
  在使用数字舵机通讯时所用到的通信方式为UART通信,但舵机只有三根接线,除去VCC和GND,只有一条通信线,也就是说要实现双向通信,只能使用单线半双工模式。在单线半双工模式下,TX 和 RX 引脚在芯片内部互连。
  1.1 配置流程
  单线半双工模式是通过设置UART_SCR寄存器的HDSEL位,在这个模式里UART_SCR 寄存器的SCEN位必须保持清零状态。
  在单线半双工模式下,TX和RX引脚在芯片内部互联,使用控制位”HALF DUPLEX SEL”(UART_SCR 中的 HDSEL 位) 选择半双工和全双工通信。
  注意:
  当选择单线半双工模式时RX 不再被使用,当有数据需要发送的时候IO才会被UART驱动,没有数据传输时TX总是被释放,所以使用单线半双工需要外部加上拉。
  除此之外通讯上和正常的UART模式类似。由于是单线半双工同一时刻总线上只能有一个节点发送,所以需要软件协议层去管理线上冲突防止多个设备同时发送,当 TXEN 位被设置时,只要数据一写到数据寄存器上,发送就继续。
  1.2 UART_SCR寄存器描述
  配置UART_SCR 的HDSEL为1
  UART_SCR 寄存器的SCEN位清零
  
举报

王明钊

2021-1-22 15:57:23
  初始化UART1
  从官网上下载MM32F013x例程,里面有UART普通模式的配置,在这个基础上我们直接调用UART_HalfDuplexCmd(UART1,ENABLE);函数接口将串口配置成单线半双工模式,然后IO口初始化只需要配置PA9 TX即可,如下:
  void UART1_NVIC_Init(u32 baudrate)
  {
  UART_InitTypeDef UART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
  //UART1 NVIC
  NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  //Baud rate
  UART_StructInit(&UART_InitStructure);
  UART_InitStructure.BaudRate = baudrate;
  //The word length is in 8-bit data format.
  UART_InitStructure.WordLength = UART_WordLength_8b;
  UART_InitStructure.StopBits = UART_StopBits_1;
  //No even check bit.
  UART_InitStructure.Parity = UART_Parity_No;
  //No hardware data flow control.
  UART_InitStructure.HWFlowControl = UART_HWFlowControl_None;
  UART_InitStructure.Mode = UART_Mode_Rx | UART_Mode_Tx;
  UART_Init(UART1, &UART_InitStructure);
  UART_HalfDuplexCmd(UART1,ENABLE); //Half Duplex Enable
  UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);
  UART_Cmd(UART1, ENABLE);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
  //UART1_TX GPIOA.9
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  }
举报

李远恒

2021-1-22 15:57:39
  功能验证测试
  UART单线半双工功能测试我们现在拿两个MM32F0133的板子一个做主机一个做从机进行单线收发测试,主机先发送一包数据给从节点,当从节点收到这包数据后再把这包数据发回给主机,然后主机和从机两个板子PA9短接到一起,外部在加一个4.7K上拉电阻。
  主机函数处理:
  uint8_t txbuff[10]= {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA};
  s32 main(void)
  {
  CONSOLE_Init(115200);//UART2 printf打印
  UART1_NVIC_Init(115200);
  printf(“UART Half Duplex TX Test rn”);
  UART1_Send_Group(txbuff,sizeof(txbuff));
  printf(“TX Data: ”);
  for(index=0;index《10;index++)
  {
  printf(“ %x ”,txbuff[index]);
  }
  printf(“rn”);
  while(1)
  {
  if(gUartRxSta == 1) //收到一包数据
  {
  gUartRxSta = 0;
  printf(“RX Data: ”);
  for(index=0;index《10;index++)
  {
  printf(“ %x ”,Rx_buff[index]);
  }
  printf(“rn”);
  memset(Rx_buff,0x00,10);
  }
  }
  //return 0;
  }
  主机UART的中断服务函数里面,将接从机发送的数据存放在Rx_buff里面,当收到一包数据后通过printf打印到串口,和原始发送的数据进行对比。
  void UART1_IRQHandler(void)
  {
  u8 recvbyte;
  // Send packet
  if (UART_GetITStatus(UART1, UART_IT_TXIEN) != RESET)
  {
  UART_ClearITPendingBit(UART1, UART_IT_TXIEN);
  }
  // Recv packet
  if (UART_GetITStatus(UART1, UART_ISR_RX) != RESET)
  {
  UART_ClearITPendingBit(UART1, UART_ISR_RX);
  recvbyte = UART_ReceiveData(UART1);
  Rx_buff[rx_cnt] = recvbyte;
  rx_cnt++;
  if(rx_cnt == 10)
  {
  gUartRxSta = 1;
  rx_cnt = 0;
  }
  }
  }
  从机函数处理:
  s32 main(void)
  {
  CONSOLE_Init(115200);//UART2 printf打印
  UART1_NVIC_Init(115200);
  printf(“UART Half Duplex RX Testrn”);
  while(1)
  {
  if(gUartRxSta == 1)//收到一包数据
  {
  gUartRxSta = 0;
  UART1_Send_Group(Rx_buff,10);
  memset(Rx_buff,0x00,10);
  }
  }
  //return 0;
  }
  从机UART的中断服务函数里面,将接主机发送的数据存放在Rx_buff里面,当收到一包数据后通过单线半双工这个串口发送回去。
  void UART1_IRQHandler(void)
  {
  u8 recvbyte;
  // Send packet
  if (UART_GetITStatus(UART1, UART_IT_TXIEN) != RESET)
  {
  UART_ClearITPendingBit(UART1, UART_IT_TXIEN);
  }
  // Recv packet
  if (UART_GetITStatus(UART1, UART_ISR_RX) != RESET)
  {
  UART_ClearITPendingBit(UART1, UART_ISR_RX);
  recvbyte = UART_ReceiveData(UART1);
  Rx_buff[rx_cnt] = recvbyte;
  rx_cnt++;
  if(rx_cnt == 10)
  {
  gUartRxSta = 1;
  rx_cnt = 0;
  }
  }
  }
  观察测试结果:
  然后我们通过主机UART2 的printf打印可以看到主机TX Data 和从机返回的RX Data数据是一样的。
  
  再看看下图逻辑分析仪抓取的逻辑波形,可以也可以看到主机发送的波形和从机返回的波形数据是一样的。
  
举报

更多回帖

发帖
×
20
完善资料,
赚取积分