OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2473|回复: 10

半双工,485,9600波特率,如何不丢数据?

[复制链接]

3

主题

14

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2019-7-29
在线时间
16 小时
发表于 2019-10-22 16:15:35 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 mian0mian903 于 2019-11-29 16:05 编辑

硬件条件:STM32F103VET6  485(波特率9600,半双工,接收 转 发送模式 需要3-4ms延时);

RTOS: rt thread 3.0.1 , 使用的是STM32   HAL库;

需求: SSCOM5.0.13 定时发送 给 开发板 8字节数据 ,(发送 0xa4  0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xaa这8字节数据,500ms 一条) ,

          如何确保每次发 开发板 都能 准确接收到这8字节数据,并回复 这8字节数据(0xa4  0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xaa) ??  各位大神 有解决方法吗?


微信图片_20191022161110.png





最佳答案

查看完整内容[请看2#楼]

1.首先 你要确定 你的485 是半双工(2线 ),还是全 双工(4线); 2.确定为 半双工 后 那么 在发送前 要 将 485收发器 的 配置为 发送 模式; 3.收发模式配置 要 看 485电路的原理图 以及 相应的 485收发器 手册。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2019-7-29
在线时间
16 小时
 楼主| 发表于 2019-10-22 16:15:36 | 显示全部楼层
gao0429 发表于 2019-11-30 14:53
485还要设置控制模式吗?  在程序上怎么体现啊

  
1.首先 你要确定 你的485 是半双工(2线 ),还是全 双工(4线);

2.确定为 半双工 后 那么 在发送前 要 将 485收发器 的 配置为 发送 模式;

3.收发模式配置  要 看 485电路的原理图  以及 相应的 485收发器 手册。
微信图片_20191130174631.png 微信图片_201911301746311.png
回复

使用道具 举报

3

主题

1155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7464
金钱
7464
注册时间
2015-1-15
在线时间
1368 小时
发表于 2019-10-22 16:51:47 | 显示全部楼层
500ms发送一次8个字节数据,通信距离和环境不恶劣的话,应该不会存在问题的
一分耕耘一分收获。
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2019-10-22
在线时间
8 小时
发表于 2019-10-22 17:05:33 | 显示全部楼层
DMA或者空闲中断模式   
回复

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
140
金钱
140
注册时间
2019-10-22
在线时间
20 小时
发表于 2019-10-23 15:20:13 | 显示全部楼层
那要看你MCU采用的什么接收方式,如果是查询接收,有可能你串口发送时正在执行别的程序,导致数据没有成功接收到。一般485通信只要不同时收和发,不会出现数据错乱的问题。
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2019-10-23 15:38:23 | 显示全部楼层
怎么接收的?
猪猪熊呢?
回复

使用道具 举报

62

主题

903

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3566
金钱
3566
注册时间
2016-1-8
在线时间
544 小时
发表于 2019-10-23 15:39:21 | 显示全部楼层
明显是你代码问题
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2019-7-29
在线时间
16 小时
 楼主| 发表于 2019-11-26 11:47:59 | 显示全部楼层
问题解决了,解决的方法为:使用中断接收, 并且把RT THREAD         USART1_IRQHandler 函数中的uart_isr(&(uart_obj[UART1_INDEX].serial))屏蔽。


初始化函数:
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */
  /* USER CODE END USART1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration   
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */       
                  __HAL_UART_DISABLE_IT(&uart->handle,UART_IT_TC);

                        __HAL_UART_ENABLE_IT(&uart->handle,UART_IT_RXNE);                                //开启中断接收
                       
                        HAL_NVIC_EnableIRQ(USART1_IRQn);       
                       
                        HAL_NVIC_SetPriority(USART1_IRQn,3,1);                                

  }

}



中断服务函数
void USART1_IRQHandler(void)
{
                static uint16_t UART_IQR_Rxbyte_Numcnt=0;
                static uint8_t         UART_IQR_Rxdata_Byte[20]={0};
                uint8_t UART_IQR_Rxdata_temp=0,sum_chk=0,xor_chk=0,neg_chk=0,crc_chk=0,dif_chk;
    /* enter interrupt */
    rt_interrupt_enter();       

//    uart_isr(&(uart_obj[UART1_INDEX].serial));   要屏蔽的函数
       
                if(UART_IQR_Rxstuts_flag==UART_IQR_Rxopen&&(__HAL_UART_GET_FLAG(&uart->handle,UART_FLAG_RXNE)!=RESET))
                {

                               
                                HAL_UART_Receive(&uart->handle,&UART_IQR_Rxdata_temp,1,0);
               
                               
               
                                if(UART_IQR_Rxbyte_Numcnt < 20)
                                {
                                                UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]=UART_IQR_Rxdata_temp;                                       
                                               
                                                switch(UART_IQR_Rxbyte_Numcnt)                                                                                                                                                                /**格式3**/
                                                {
/******************************************帧头确认***********************************************************/                                                       
                                                        case 0:                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=0x41)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
                                                        case 1:                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=0x34)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
                                                        case 2:                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=0x41)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
                                                        case 3:                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=0x32)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
                                                        case 4:                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=0x46)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
/******************************************目标地址取反校验************************************************/       
                                                        case 6:                neg_chk= ~UART_IQR_Rxdata_Byte[5];
                                                                                                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=neg_chk)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
/******************************************ID校验 取反校验************************************************/                                                                                                       
                                                        case 8:                neg_chk= ~UART_IQR_Rxdata_Byte[7];
                                                                                                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=neg_chk)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;                               
/****************************************1帧8字节数据累加校验、异或校验**********************************************/                                                                                                                                                                                               
                                                        case 17:        sum_chk = (        UART_IQR_Rxdata_Byte[9]        +UART_IQR_Rxdata_Byte[10]        +UART_IQR_Rxdata_Byte[11]+UART_IQR_Rxdata_Byte[12]+
                                                                                                                                        UART_IQR_Rxdata_Byte[13]        +UART_IQR_Rxdata_Byte[14]                          +UART_IQR_Rxdata_Byte[15]+UART_IQR_Rxdata_Byte[16]);
                                                       
                                                                        xor_chk = (        UART_IQR_Rxdata_Byte[9]        ^UART_IQR_Rxdata_Byte[10]        ^UART_IQR_Rxdata_Byte[11]^UART_IQR_Rxdata_Byte[12]^
                                                                                                                                        UART_IQR_Rxdata_Byte[13]        ^UART_IQR_Rxdata_Byte[14]            ^UART_IQR_Rxdata_Byte[15]^UART_IQR_Rxdata_Byte[16]);
                                                                                               
                                                                                                dif_chk = sum_chk>xor_chk?(sum_chk-xor_chk)xor_chk-sum_chk);
                                                       
                                                                                                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=dif_chk)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;

                                                        case 18:        crc_chk=crc8_rohc(&UART_IQR_Rxdata_Byte[9], 8);                                                                                                                                                                                                                                                                                               
                                                                                                if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=crc_chk)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
/******************************************帧尾确认********************************************************/       
                                                        case 19:        if(UART_IQR_Rxdata_Byte[UART_IQR_Rxbyte_Numcnt]!=0xED)
                                                                                                {
                                                                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                                                                }else(UART_IQR_Rxbyte_Numcnt++);break;
                                                        default :        UART_IQR_Rxbyte_Numcnt++;break;
                                                }
                                               
                                }
                                                       
                                if(UART_IQR_Rxbyte_Numcnt==20)
                                {                       
                                                        UART_IQR_Rxstuts_flag=UART_IQR_Rxclose;
                                                        UART_IQR_Rxbyte_Numcnt=0;
                                                        rt_sem_release(SemFor_uart_com);
                                                        UART_IQR_Rxflame.addr        = UART_IQR_Rxdata_Byte[5];
                                                        UART_IQR_Rxflame.id                = UART_IQR_Rxdata_Byte[7];
                                                        memcpy(UART_IQR_Rxflame.data,&UART_IQR_Rxdata_Byte[9],8);
                                }       
                        }
       

    /* leave interrupt */
    rt_interrupt_leave();
}


微信图片_20191126091530.png
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-8-16
在线时间
6 小时
发表于 2019-11-26 15:05:28 | 显示全部楼层
楼主能分享一下你的代码吗  我也遇到了相同的问题  求翻  也是通过这个协议485接口给传感器发数据  但就是接收不到  希望能帮助我一下   有偿也可以    谢谢  否则做不出来   跳楼的心思都有了哭哭哭哭哭
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2019-7-29
在线时间
16 小时
 楼主| 发表于 2019-11-29 16:01:45 | 显示全部楼层
gao0429 发表于 2019-11-26 15:05
楼主能分享一下你的代码吗  我也遇到了相同的问题  求翻  也是通过这个协议485接口给传感器发数据  但:' ...

HAL_UART_Transmit(&uart->handle,UART_RXbuff_copy,10,TX_TIMEOUT);       

这个是我的发送 函数, 发送不 应该是 相对容易处理的  问题吗? 你是不是 发送的时候 没把485收发器 配置为  发送模式?
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-8-16
在线时间
6 小时
发表于 2019-11-30 14:53:32 | 显示全部楼层
mian0mian903 发表于 2019-11-29 16:01
HAL_UART_Transmit(&uart->handle,UART_RXbuff_copy,10,TX_TIMEOUT);       

这个是我的发送 函数, 发送不  ...

485还要设置控制模式吗?  在程序上怎么体现啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-24 21:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表