[应用方案] 新唐cortex-m0之RS485通讯

[复制链接]
 楼主| 仙女山 发表于 2015-7-6 14:01 | 显示全部楼层 |阅读模式
如果大家用的新唐的板子的话,而又要用485通讯功能,一定会去参考自带的UART_DEMO示例程序。新唐的实例程序分为两种类型,一种就是寄存器版本的,一种叫做API版本的。如果用API写程序的同仁们,一定会非常欣慰,因为这个示例程序就是485的,只要改改就行了,而用寄存器版本写程序的一定非常苦恼(笔者就是一直用寄存器版本的写程序),因为它就是一个普通的UART通讯功能,很多人会想着看看API的版本的,慢慢翻译成寄存器版本的,但是两者有些区别,经过这两天的深入,我已经把API版本改成了寄存器版本,改的是面目全非,因为我的初始化代码几乎和API的版本的一样,但是它能运行出结果,而我不行,这如何不叫人纠结呢?  在新唐的两个版本中,有这样两个区别,大家需要注意的:
  1.   API版本中,用的UART时钟是内部的22MHZ的晶振,大家一定看到了算晶振的波特率的函数,所以没有深入看,只知道可以得出自己想要的晶振就可以了(一般用9600的波特率),而寄存器版本中用的还是外部的12MHZ晶振
  2.    第二个不同的地方也是我纠结了3个星期终于发现了,也是我的问题所在的,就是API版本中,配置了管脚为RTS0功能,而寄存器版本中没有,所以即使后面初始化和API非常相似,也出不来结果,这是一个很重要的原因!(RTS0功能就是自动方向控制,是485中用来控制收发的)
解决了这两个问题,485通讯来说,基本就可以平坦大道了,但是这样说也许很空虚,下面附上485的电路图和485初始化的寄存器版本的代码,希望对大家有帮助,只是新唐Cortex-M0的代码,如果不是这个芯片的可以看看步骤,应该也没有什么太大问题。

如下图就是RS85通讯的电路图:


下面是代码部分:

  1.     #define UARTClkSource_in22MHZ   (CLKSEL1 = ((CLKSEL1 & (~UART_CLK)) | UART_22M))  
  2. #define UART0_Clock_EN    APBCLK |= UART0_CLKEN   // Enable UART0 clock
  3.     void UART_Init(void)  
  4.     {  
  5.         /* Step 1. GPIO initial */   
  6.         P3_MFP &= ~(P31_TXD0 | P30_RXD0);     
  7.         P3_MFP |= (TXD0 | RXD0);            //P3.0 --> UART0 RX  
  8.                                 //P3.1 --> UART0 TX  
  9.       
  10.         P0_MFP &= ~(P03_AD3_RTS0 | P02_AD2_CTS0);  
  11.         P0_MFP |= (RTS0 | CTS0);            //P0.3---->RTS0自动方向控制  
  12.                                         //这里就是配置的地方,笔者就是这里错了,导致了3个星期没有出来,         
  13.         /* Step 2. Enable and Select UART clock source  */  
  14.         UART0_Clock_EN;         //UART Clock Enable, APBCLK[16]:1  
  15.       //UARTClkSource_ex12MHZ;  //UART Clock is ext12MHz, CLKSEL1[25,24]: 00  
  16.         UARTClkSource_in22MHZ;  //使用内部22MHZ晶振  
  17.         CLKDIV &= ~(15<<8);   //UART Clock DIV Number = 0;  
  18.                                                                
  19.         /* Step 3. Select Operation mode */  
  20.         IPRSTC2 |= UART0_RST;   //Reset UART0  
  21.         IPRSTC2 &= ~UART0_RST;  //Reset end  
  22.         UA0_FCR |= TX_RST;      //Tx FIFO Reset  
  23.         UA0_FCR |= RX_RST;      //Rx FIFO Reset  
  24.         UA0_FCR |= RFITL_1;     //设置为1个字节触发中断  
  25.       
  26.         UA0_LCR &= (~SPE);  
  27.         UA0_LCR &= (~EPE);  
  28.         UA0_LCR &= (~PBE);      //Parity Bit Disable  校验禁止  
  29.       
  30.         UA0_LCR &= ~WLS;  
  31.         UA0_LCR |= WL_8BIT;     //8 bits Data Length  8位长度  
  32.         UA0_LCR &= NSB_ONE;     //1 stop bit          1位停止位  
  33.       
  34.         /* Step 4. Set BaudRate to 115200*/  
  35.         //UA0_BAUD |= DIV_X_EN;   //Mode2:DIV_X_EN = 1  
  36.         //UA0_BAUD |= DIV_X_ONE;  //Mode2:DIV_X_ONE =1  
  37.       //上面是使用12M晶振的波特率设置  
  38.     UA0_BAUD &= (~(1<<29));       //    UA0_BAUD |= (1<< 29);   //Mode2:DIV_X_EN = 1  
  39.     UA0_BAUD &= (~(1<< 28));          //    UA0_BAUD |= (1<< 28);  //Mode2:DIV_X_ONE =1  
  40. UA0_BAUD |= ( 22118400UL / 9600/16  -2);
  41. /UA0_BAUD |= ((11059200 / 115200) -2); //Set BaudRate to 115200;  
  42. >void initRS485(void)  
  43. {  
  44. UA0_FUN_SEL = RS485_EN;        //设置为485功能  
  45. UA0_FCR |= (RX_DIS);           //禁止接收器接受</p><p> UA0_RS485_CSR |= RS485_NMM;    //设置为485普通操作模式  
  46. UA0_RS485_CSR |= RS485_AUD;    //设置为控制自动方向模式</p><p> </p><p> /* 开启UART0中断 */  
  47. UA0_IER |= RDA_IEN;           //开启可接受数据中断和  
  48. UA0_IER |= RLS_IEN;           //接收器上中断状态使能,是一个错误中断,见M0手册</p><p> NVIC_ISER |= UART0_INT;  
  49. // NVIC_IPR3 |= UART0_PRI0;      //设置优先级为3(最小优先级)  
  50. }
  1. void initRS485(void)  
  2. {  
  3.     UA0_FUN_SEL = RS485_EN;                 //设置为485功能  
  4.     UA0_FCR |= (RX_DIS);                    //禁止接收器接受  
  5.   
  6.     UA0_RS485_CSR |= RS485_NMM;             //设置为485普通操作模式  
  7.     UA0_RS485_CSR |= RS485_AUD;             //设置为控制自动方向模式  
  8.   
  9. //  UA0_IER |= AUTO_RTS_EN;  
  10. //  UA0_FCR  |= RTS_TRI_4;  
  11. //  UA0_MCR |= (LEV_RTS_H);                 //设置RTS为1,使能485驱动器  
  12.   
  13.     /* 开启UART0中断 */  
  14.     UA0_IER |= RDA_IEN;                     //开启可接受数据中断和  
  15.     UA0_IER |= RLS_IEN;                     //接收器上中断状态使能  
  16.   
  17.     NVIC_ISER |= UART0_INT;  
  18. //  NVIC_IPR3 |= UART0_PRI0;                //设置优先级为3(最小优先级)  
  19. }  





芙蓉洞 发表于 2015-7-6 14:37 | 显示全部楼层
非常详细的资料,谢谢楼主的热心分享
quray1985 发表于 2015-7-7 15:24 | 显示全部楼层
这个资料给的够详细的,谢谢楼主的分享
gaoyang9992006 发表于 2015-7-7 20:58 | 显示全部楼层
API版本中,用的UART时钟是内部的22MHZ的晶振,大家一定看到了算晶振的波特率的函数,所以没有深入看,只知道可以得出自己想要的晶振就可以了(一般用9600的波特率),而寄存器版本中用的还是外部的12MHZ晶振
楼主研究的真仔细啊。
Harvard 发表于 2015-7-8 23:49 | 显示全部楼层
我喜欢自己用io切换485 .或者设置一个三极管 搞成自动切换. 这样也无所谓485模式了.
cowboy2014 发表于 2015-7-9 08:28 | 显示全部楼层
第二个不同的地方也是我纠结了3个星期终于发现了,也是我的问题所在的,就是API版本中,配置了管脚为RTS0功能,而寄存器版本中没有,所以即使后面初始化和API非常相似,也出不来结果,这是一个很重要的原因!(RTS0功能就是自动方向控制,是485中用来控制收发的)
解决了这两个问题,485通讯来说,基本就可以平坦大道了,但是这样说也许很空虚,下面附上485的电路图和485初始化的寄存器版本的代码,希望对大家有帮助,只是新唐Cortex-M0的代码,如果不是这个芯片的可以看看步骤,应该也没有什么太大问题。

楼主研究的真透彻
 楼主| 仙女山 发表于 2015-7-9 09:20 | 显示全部楼层
楼主确实看的很详细,一般人注意不到这些
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

340

帖子

2

粉丝