[技术问答] M0518串口电平问题求助: 通信经常性存在乱码

[复制链接]
 楼主| Harvard 发表于 2016-4-17 13:42 | 显示全部楼层 |阅读模式
本帖最后由 Harvard 于 2016-4-17 13:44 编辑

     

目前应用M0518进行一个多串口数据采集装置的产品设计, 样机制作成功后, 现在做整体测试, 发现一个问题.

波特率为:9600bps,  8/n/1, TTL交叉互联通信.

产品中,有与GSM手机模块通信, 其串口电平是2.8V, 单片机是采用 3.3v供电 .目前的情况是, GSM模块发过来的信息,总有个别会存在误码, 疑似串口的电平不一致导致.  想请教有没有什么简单的方法,来实现电平的兼容.按照Datasheet所示, 2.8v 应该在3.3v的范围之内.


   当通过下列语句对MFP等设置后,是否还有必要对串口所在的引脚的GPIO模式进行设置, 希望大家指导.


//If the defines do not exist in your project, please refer to the related sys.h in the sys_h folder appended to the tool package.
SYS->ALT_MFP = 0x00000000;
SYS->ALT_MFP2 = 0x00000000;
SYS->ALT_MFP3 = 0x00000000;
SYS->ALT_MFP4 = SYS_ALT_MFP4_PA3_UART3_RXD | SYS_ALT_MFP4_PA2_UART3_TXD |
SYS_ALT_MFP4_PA1_UART5_RXD | SYS_ALT_MFP4_PA0_UART5_TXD;
SYS->GPA_MFP = SYS_GPA_MFP_PA3_UART3_RXD | SYS_GPA_MFP_PA2_UART3_TXD |
SYS_GPA_MFP_PA1_UART5_RXD | SYS_GPA_MFP_PA0_UART5_TXD;
SYS->GPB_MFP = SYS_GPB_MFP_PB5_UART1_TXD | SYS_GPB_MFP_PB4_UART1_RXD |
SYS_GPB_MFP_PB1_UART0_TXD | SYS_GPB_MFP_PB0_UART0_RXD;
SYS->GPC_MFP = SYS_GPC_MFP_PC7_UART4_RXD | SYS_GPC_MFP_PC6_UART4_TXD;
SYS->GPD_MFP = SYS_GPD_MFP_PD15_UART2_TXD | SYS_GPD_MFP_PD14_UART2_RXD;
SYS->GPF_MFP = SYS_GPF_MFP_PF7_ICE_DAT | SYS_GPF_MFP_PF6_ICE_CLK;

以上是nuvoton pinconfig工具产生的代码 ,使用感觉不错.  是否还不需要对串口所在引脚做GPIO设定呢.

/* PB口上串口0: txd rxd  GPIO模式处理 */
GPIO_SetMode(PB,BIT,GPIO_PMD_OUTPUT);

GPIO_SetMode(PB,BIT0,GPIO_PMD_QUASI);



 楼主| Harvard 发表于 2016-4-17 13:49 | 显示全部楼层



  1. u16  _crc16_update0(u16 crc, u08 a)
  2. {
  3.         int i;
  4.         crc ^= a;
  5.         for (i = 0; i < 8; ++i)
  6.         {
  7.             if (crc & 1)
  8.                 crc = (crc >> 1) ^ 0xA001;
  9.             else
  10.                 crc = (crc >> 1);
  11.         }
  12.         return crc;
  13. }

  14. /*
  15. ** 串行口初始化
  16. ** baudrate取值为: 48 96 192
  17. */

  18. void usart0_init(u16 baudrate)
  19. {
  20.         /* Unlock protected registers */
  21.     SYS_UnlockReg();
  22.    
  23.          /* Reset UART0 module */
  24.     SYS_ResetModule(UART0_RST);
  25.                
  26.         /* Enable UART clock */
  27.      CLK_EnableModuleClock(UART0_MODULE);

  28.         /*---------------------------------------------------------------------------------------------------------*/
  29.         /* Init UART                                                                                               */
  30.         /*---------------------------------------------------------------------------------------------------------*/

  31.     /* 选择uart功能 */
  32.     UART0->FUN_SEL = UART_FUNC_SEL_UART;

  33.     /* Tx FIFO Reset & Rx FIFO Reset & FIFO Mode Enable */
  34.         //_UART_FLUSH_FIFO(UART0,UART_FCR_TFR_Msk | UART_FCR_RFR_Msk);
  35.     UART0->FCR |=UART_FCR_TFR_Msk | UART_FCR_RFR_Msk;

  36.     /* 选择RX FIFO的阀值为1BYTE*/
  37.      _UART_SET_RX_TRG_LEV(UART0,UART_FCR_RFITL_1BYTE);
  38.      
  39.     if( baudrate != 9600 && baudrate != 19200 && baudrate != 4800&&baudrate != 2400 ) baudrate  = 2400;//默认值

  40.     /* Set 115200 baudrate according to 50MHz system clock */
  41.   //UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__IRC22M, baudrate);
  42.       UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HXT, baudrate);
  43.    
  44.     /* 设置串口的工作方式 */   
  45.    _UART_SET_DATA_FORMAT(UART0, UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1);


  46.         /* Lock protected registers */
  47.     SYS_LockReg();


  48.     /* Enable RDA\RLS\Time-out Interrupt  */
  49.     UART_ENABLE_INT(UART0, (UART_IER_RDA_IEN_Msk ));
  50.    
  51.     /* 开串口中断 */
  52.     NVIC_EnableIRQ(UART02_IRQn);

  53. }
  54. /*
  55. *        通信辅助功能控制开关
  56. */

  57. void usart0_dis_recv(void)
  58. {
  59.     _UART_DISABLE_INT(UART0,UART_IER_RDA_IEN_Msk);
  60.     //_UART_RS485_SET_RXDISABLE(UART0);
  61.     UART0->FCR |= UART_FCR_RX_DIS_Msk; /*  Disable RS485 RX*/
  62.    
  63.    
  64. }
  65. void usart0_en_recv (void)
  66. {
  67.     _UART_ENABLE_INT(UART0,UART_IER_RDA_IEN_Msk);
  68.     //_UART_RS485_CLEAR_RXDISABLE(UART0);
  69.     UART0->FCR &= ~ UART_FCR_RX_DIS_Msk;  /* Enable RS485 RX */
  70.    
  71.      UART0_SEND = 0;

  72.     /* 因为无法关闭串口接收,只能重新清楚FIFO并且消除RDA_IF标志位*/
  73. //        _UART_FLUSH_FIFO(UART0,UART_FCR_RFR_Msk);

  74. }

  75. /*超时定时器初始化及其开关控制*/
  76. #define T3_TICK_MIN                1000000/(F_CPU/1024)
  77. #define T3_TICK                        1000        //1ms
  78. #define TIMER3_BGN_VAL          (255-T3_TICK/T3_TICK_MIN)

  79. //static u08 CNT_t15=0;                        //1.5字符时间
  80. //static u08 CNT_t35=0;                        //3.5字符时间
  81. static u08 SYS_t3_cnt_frame=0;                //时间间隔计数器,用于1.5 和3.5字符时间判断
  82. u08     SYS_t3_on = OFF ;     //用于1.5 3.5字符判断的软定时器 开关.


  83. void timer3_on(void)
  84. {
  85.    
  86.     SYS_t3_cnt_frame = 0 ;
  87.     SYS_t3_on = ON;
  88. }
  89. void timer3_off(void)
  90. {
  91.     SYS_t3_on = OFF;
  92.     /** 帧间隔控制 */
  93.     SYS_t3_cnt_frame = 0;

  94. }

  95. /**
  96. * [url=home.php?mod=space&uid=247401]@brief[/url]       Timer-3 IRQ
  97. *
  98. * @param       None
  99. *
  100. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  101. *
  102. * [url=home.php?mod=space&uid=1543424]@Details[/url]     The TIMER2 default IRQ, declared in startup_M051Series.s.
  103. */
  104. void TMR3_IRQHandler(void)
  105. {
  106.     /* Clear TIMER2 Timeout Interrupt Flag */
  107.     _TIMER_CLEAR_CMP_INT_FLAG(TIMER3);   

  108.     /* 如果定时器打开 */
  109.     if( SYS_t3_on == ON )
  110.    {
  111.           SYS_t3_cnt_frame++;
  112.          
  113.           if ( SYS_t3_cnt_frame > T35)         //a frame was finished
  114.           {
  115.                usart0_dis_recv();          //禁止接收中断

  116.                timer3_off ()          ;   //tunr off timer;

  117.                SYS_t3_cnt_frame = 0 ;   //reset timer

  118.                RxBufPtr--;                         //调整指针        

  119.                fFrameDone    = OK;   //frame is completed
  120.                
  121.                LED_DTU = 1;
  122.            }      
  123.     }
  124.     /* 定时器关,还未进行帧间隔判断 */
  125.    else
  126.    {
  127.         SYS_t3_cnt_frame = 0;
  128.    }
  129.    
  130. }



  131. u08 RxBuf[MAX_BUF_LEN]={0,1,2,3,4};
  132. u08 TxBuf[MAX_BUF_LEN];
  133. u08 RxBufPtr         = RX_BUF_BGN_ADR;
  134. u08 TxBufPtr         = TX_BUF_BGN_ADR1;
  135. BOOL fIsRXING        = NO;          //is receiving now
  136. BOOL fIsTXING        = NO;          //is transsending now
  137. BOOL fRxBufFull        = NO;
  138. BOOL fTxBufFull = NO;
  139. BOOL fFrameDone = NO;                   //one frame finished
  140. BOOL fFrameBad = NO;                   //frame was broken
  141. u16  CRC                = 0xFFFF;           //CRC初始值       


  142. /*接收中断*/
  143. void UART02_IRQHandler( void )
  144. {
  145.     /* 1-定义临时变量获取中断标志   */
  146.     uint32_t u32IntSts= UART0->ISR;
  147.    
  148.     /* 2- 判断是否是RDA中断        */
  149.     // 2-1:串口0处理
  150.      if( UART_GET_INT_FLAG(UART0,UART_ISR_RDA_INT_Msk) )
  151.     {
  152.         /* 通信指示灯处理 */
  153.          LED_DTU = 0;
  154.         
  155.         /* 查询串口的RDA */
  156.         while(_UART_IS_RX_READY(UART0))
  157.         {
  158.             /* Get the character from UART Buffer
  159.             *   BSP接收数据
  160.             */
  161.             RxBuf[RxBufPtr] = UART_READ(UART0);
  162.             
  163.            /* 复位定时器  */
  164.            SYS_t3_cnt_frame = 0 ;   

  165.             /*new frame coming*/
  166.             if( RxBufPtr == RX_BUF_BGN_ADR )//新的一帧开始
  167.             {
  168.                 CRC = 0xffff        ;                    //准备crc计算,

  169.                 timer3_on();                    //开启定时器计时
  170.             }

  171.             /*with a frame and RxBuf is not full*/
  172.             /*when we detect a frame was borken according to t15 ,
  173.             * we keep on receiving in order to synchronize the frame  
  174.             */
  175.             else if
  176.               ( RxBufPtr < MAX_BUF_LEN -1)
  177.             {  
  178.                 if ( SYS_t3_cnt_frame > T15 && SYS_t3_cnt_frame < T35 )
  179.                 {
  180.                      SYS_t3_cnt_frame = 0 ;   //reset timer
  181.                
  182.                      fFrameBad     = TRUE; //frame is broken
  183.                 }
  184.             }

  185.             /*RxBuf full */
  186.             /*
  187.             **
  188.             */
  189.             else if
  190.             ( RxBufPtr >= MAX_BUF_LEN -1)
  191.             {
  192.                 usart0_dis_recv()    ;                         //stop receving
  193.             
  194.                 timer3_off ()            ;            //tunr off timer;

  195.                 fRxBufFull           = YES ;            //缓冲区已满
  196.                
  197.                 fFrameBad     = TRUE;            //frame is broken
  198.                
  199.                 RxBufPtr --;                             //指针保持不变,防止破坏其他数据区
  200.             
  201.                 LED_DTU = 1;
  202.             }
  203.                
  204.                 CRC = _crc16_update0( CRC,RxBuf[RxBufPtr] );

  205.                 RxBufPtr++;                                                //adjust pointer
  206.         }//end while
  207.       

  208.         
  209.      }//end if
  210.     // END 2-1:串口0处理
  211.    
  212.     // 2-1:串口2处理
  213.      
  214.      

  215. }

  216. /*查询发送*/
  217. void usart0_send_byte( u08 txbyte )
  218. {
  219.      UART0_SEND = 1;
  220.     _UART_SENDBYTE( UART0,txbyte );
  221.     _UART_WAIT_TX_EMPTY( UART0 );
  222. }

heisexingqisi 发表于 2016-4-17 21:43 | 显示全部楼层
只要能用就好,不知道电平问题是什么问题,你用示波器看看没,是电压达不到吗
tcchiu1 发表于 2016-4-25 17:26 | 显示全部楼层
M0518的串口,每一组的FIFO大小,好像是不一样了。这一点你有注意到吗??
liuyu305 发表于 2016-4-25 17:50 | 显示全部楼层
我还遇到过串口能收不能发的问题。换个片子就好了。
secretuniverse 发表于 2016-4-25 21:26 | 显示全部楼层
你用示波器看看电平是否是稳定的
643757107 发表于 2016-4-25 22:16 | 显示全部楼层
记得搞个上拉电阻,防止外界干扰,另外速度一般控制在9600就行了,如果是晶振的震源,就要看晶振是否靠谱了,要不实际的波特率不对。
 楼主| Harvard 发表于 2016-4-26 23:02 | 显示全部楼层
谢谢指点. 经查 是GSM模块引起的干扰. 电源加强后,现象消失
huangcunxiake 发表于 2016-4-26 23:06 | 显示全部楼层
电源加强后,现象消失??什么意思,这是怎么干扰到串口的?是电压不稳定吗
734774645 发表于 2016-4-27 19:55 | 显示全部楼层
/*查询发送*/
void usart0_send_byte( u08 txbyte )
{
     UART0_SEND = 1;
    _UART_SENDBYTE( UART0,txbyte );
    _UART_WAIT_TX_EMPTY( UART0 );
}
Roderman_z 发表于 2016-4-27 21:07 | 显示全部楼层
你的出现的情况是死机还是不能正常接收呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

74

主题

1731

帖子

21

粉丝
快速回复 在线客服 返回列表 返回顶部