[DemoCode下载] M058S的485主机模式通信

[复制链接]
1358|14
 楼主| zhuotuzi 发表于 2017-1-28 09:52 | 显示全部楼层 |阅读模式
  1. /****************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
  4. * $Revision: 3 $
  5. * $Date: 15/02/06 10:22a $
  6. * @brief
  7. *           Transmit and receive data in UART RS485 mode.
  8. *           This sample code needs to work with UART_RS485_Slave.
  9. * @note
  10. * Copyright (C) 2011 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "M058S.h"


  15. #define PLL_CLOCK       50000000


  16. #define RXBUFSIZE       128

  17. #define MATCH_ADDRSS    0xC0
  18. #define UNMATCH_ADDRSS  0xB1


  19. /*---------------------------------------------------------------------------------------------------------*/
  20. /* Define functions prototype                                                                              */
  21. /*---------------------------------------------------------------------------------------------------------*/
  22. extern char GetChar(void);
  23. int32_t main(void);
  24. void RS485_SendAddressByte(uint8_t u8data);
  25. void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes);
  26. void RS485_9bitModeMaster(void);


  27. /*---------------------------------------------------------------------------------------------------------*/
  28. /*  RS485 Transmit Control  (Address Byte: Parity Bit =1 , Data Byte:Parity Bit =0)                        */
  29. /*---------------------------------------------------------------------------------------------------------*/
  30. void RS485_SendAddressByte(uint8_t u8data)
  31. {
  32.     /* Set UART parity as MARK and ship baud rate setting */
  33.     UART_SetLine_Config(UART0, 0, UART_WORD_LEN_8, UART_PARITY_MARK, UART_STOP_BIT_1);

  34.     /* Send data */
  35.     UART_WRITE(UART0, u8data);

  36.     /* Wait Tx empty */
  37.     UART_WAIT_TX_EMPTY(UART0);
  38. }

  39. void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
  40. {
  41.     /* Set UART parity as SPACE and ship baud rate setting */
  42.     UART_SetLine_Config(UART0, 0, UART_WORD_LEN_8, UART_PARITY_SPACE, UART_STOP_BIT_1);

  43.     /* Send data */
  44.     UART_Write(UART0, pu8TxBuf, u32WriteBytes);
  45. }

  46. /*---------------------------------------------------------------------------------------------------------*/
  47. /*  RS485 Transmit Test                                                                                    */
  48. /*---------------------------------------------------------------------------------------------------------*/
  49. void RS485_9bitModeMaster()
  50. {
  51.     int32_t i32;
  52.     uint8_t g_u8SendData[RXBUFSIZE] = {0};

  53.     printf("\n");
  54.     printf("+-------------------------------------------------------------+\n");
  55.     printf("|     Pin Configure                                           |\n");
  56.     printf("+-------------------------------------------------------------+\n");
  57.     printf("|     _______                                    _______      |\n");
  58.     printf("|    |       |                                  |       |     |\n");
  59.     printf("|    |Master |--- TXD(P3.1) <====> RXD(P3.0) ---| Slave |     |\n");
  60.     printf("|    |       |--- RTS(P0.3) <====> RTS(P0.3) ---|       |     |\n");
  61.     printf("|    |_______|                                  |_______|     |\n");
  62.     printf("|                                                             |\n");
  63.     printf("+-------------------------------------------------------------+\n");
  64.     printf("|  Please enable semihosted to show messages on debug session.|\n");
  65.     printf("|  Keil users must define DEBUG_ENABLE_SEMIHOST in both C/C++ |\n");
  66.     printf("|  and Asm preprocessor symbols.                              |\n");
  67.     printf("|  IAR users must define DEBUG_ENABLE_SEMIHOST in both C/C++  |\n");
  68.     printf("|  Compiler and Assembler preprocessor symbols.               |\n");
  69.     printf("+-------------------------------------------------------------+\n");

  70.     /*
  71.         The sample code is used to test RS485 9-bit mode and needs
  72.         two Module test board to complete the test.
  73.         Master:
  74.             1.Set AUD mode and HW will control RTS pin. LEV_RTS is set to '0'.
  75.             2.Master will send four different address with 10 bytes data to test Slave.
  76.             3.Address bytes : the parity bit should be '1'. (Set UA_LCR = 0x2B)
  77.             4.Data bytes : the parity bit should be '0'. (Set UA_LCR = 0x3B)
  78.             5.RTS pin is low in idle state. When master is sending,
  79.               RTS pin will be pull high.

  80.         Slave:
  81.             1.Set AAD and AUD mode firstly. LEV_RTS is set to '0'.
  82.             2.The received byte, parity bit is '1' , is considered "ADDRESS".
  83.             3.The received byte, parity bit is '0' , is considered "DATA".  (Default)
  84.             4.AAD: The slave will ignore any data until ADDRESS match ADDR_MATCH value.
  85.               When RLS and RDA interrupt is happened,it means the ADDRESS is received.
  86.               Check if RS485_ADD_DETF is set and read UA_RBR to clear ADDRESS stored in rx_fifo.

  87.               NMM: The slave will ignore data byte until disable RX_DIS.
  88.               When RLS and RDA interrupt is happened,it means the ADDRESS is received.
  89.               Check the ADDRESS is match or not by user in UART_IRQHandler.
  90.               If the ADDRESS is match,clear RX_DIS bit to receive data byte.
  91.               If the ADDRESS is not match,set RX_DIS bit to avoid data byte stored in FIFO.
  92.     */

  93.     printf("\n");
  94.     printf("+-------------------------------------------------------------+\n");
  95.     printf("|            RS485  Function Test (9-bit Master)              |\n");
  96.     printf("+-------------------------------------------------------------+\n");
  97.     printf("| The function will send address with 128 data bytes to test  |\n");
  98.     printf("| RS485 9-bit mode. Please connect TX/RX to another board and |\n");
  99.     printf("| wait its ready to receive.                                  |\n");
  100.     printf("| Press any key to start...                                   |\n");
  101.     printf("+-------------------------------------------------------------+\n\n");
  102.     GetChar();

  103.     /* Set RS485-Master as AUD mode */
  104.     /* Enable AUD mode to HW control RTS pin automatically */
  105.     /* You also can use GPIO to control RTS pin for replacing AUD mode*/
  106.     UART_SelectRS485Mode(UART0, UART_ALT_CSR_RS485_AUD_Msk, 0);

  107.     /* Set RTS pin active level as high level active */
  108.     UART0->MCR &= ~UART_MCR_LEV_RTS_Msk;
  109.     UART0->MCR |= UART_RTS_IS_HIGH_LEV_ACTIVE;

  110.     /* Set TX delay time */
  111.     UART0->TOR = 0x2000;

  112.     /* Prepare Data to transmit */
  113.     for(i32 = 0; i32 < RXBUFSIZE; i32++)
  114.     {
  115.         g_u8SendData[i32] = i32 & 0xFF;
  116.     }

  117.     /* Send address and data for test */
  118.     printf("Send Address 0x%x and data 0~127\n", MATCH_ADDRSS);
  119.     RS485_SendAddressByte(MATCH_ADDRSS);
  120.     RS485_SendDataByte(g_u8SendData, RXBUFSIZE);

  121.     printf("Transfer Done\n");

  122. }

  123. void SYS_Init(void)
  124. {
  125.     /*---------------------------------------------------------------------------------------------------------*/
  126.     /* Init System Clock                                                                                       */
  127.     /*---------------------------------------------------------------------------------------------------------*/

  128.     /* Enable Internal RC 22.1184MHz clock */
  129.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  130.     /* Waiting for Internal RC clock ready */
  131.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

  132.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  133.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

  134.     /* Enable external XTAL 12MHz clock */
  135.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  136.     /* Waiting for external XTAL clock ready */
  137.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  138.     /* Set core clock as PLL_CLOCK from PLL */
  139.     CLK_SetCoreClock(PLL_CLOCK);

  140.     /* Enable UART module clock */
  141.     CLK_EnableModuleClock(UART0_MODULE);

  142.     /* Select UART module clock source */
  143.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

  144.     /*---------------------------------------------------------------------------------------------------------*/
  145.     /* Init I/O Multi-function                                                                                 */
  146.     /*---------------------------------------------------------------------------------------------------------*/

  147.     /* Set P3 multi-function pins for UART0 RXD and TXD */
  148.     SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
  149.     SYS->P3_MFP |= (SYS_MFP_P30_RXD | SYS_MFP_P31_TXD);

  150.     /* Set P0 multi-function pins for UART0 RTS */
  151.     SYS->P0_MFP = SYS->P0_MFP & (~SYS_MFP_P03_Msk) | SYS_MFP_P03_RTS;

  152. }

  153. void UART0_Init()
  154. {
  155.     /*---------------------------------------------------------------------------------------------------------*/
  156.     /* Init UART                                                                                               */
  157.     /*---------------------------------------------------------------------------------------------------------*/
  158.     /* Reset UART0 */
  159.     SYS_ResetModule(UART0_RST);

  160.     /* Configure UART0 and set UART0 Baudrate */
  161.     UART_Open(UART0, 115200);
  162. }

  163. /*---------------------------------------------------------------------------------------------------------*/
  164. /* MAIN function                                                                                           */
  165. /*---------------------------------------------------------------------------------------------------------*/
  166. int main(void)
  167. {
  168.     /* Unlock protected registers */
  169.     SYS_UnlockReg();

  170.     /* Init System, peripheral clock and multi-function I/O */
  171.     SYS_Init();

  172.     /* Lock protected registers */
  173.     SYS_LockReg();

  174.     /* Init UART0 for testing */
  175.     UART0_Init();

  176.     /*---------------------------------------------------------------------------------------------------------*/
  177.     /* SAMPLE CODE                                                                                             */
  178.     /*---------------------------------------------------------------------------------------------------------*/

  179.     printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);

  180.     printf("\n\nUART Sample Program\n");

  181.     /* UART RS485 sample master function */
  182.     RS485_9bitModeMaster();

  183.     while(1);

  184. }


 楼主| zhuotuzi 发表于 2017-1-28 09:53 | 显示全部楼层
/*---------------------------------------------------------------------------------------------------------*/
/*  RS485 Transmit Control  (Address Byte: Parity Bit =1 , Data Byte:Parity Bit =0)                        */
/*---------------------------------------------------------------------------------------------------------*/
void RS485_SendAddressByte(uint8_t u8data)
{
    /* Set UART parity as MARK and ship baud rate setting */
    UART_SetLine_Config(UART0, 0, UART_WORD_LEN_8, UART_PARITY_MARK, UART_STOP_BIT_1);

    /* Send data */
    UART_WRITE(UART0, u8data);

    /* Wait Tx empty */
    UART_WAIT_TX_EMPTY(UART0);
}

void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
{
    /* Set UART parity as SPACE and ship baud rate setting */
    UART_SetLine_Config(UART0, 0, UART_WORD_LEN_8, UART_PARITY_SPACE, UART_STOP_BIT_1);

    /* Send data */
    UART_Write(UART0, pu8TxBuf, u32WriteBytes);
}
这两个一个发送地址一个发送数据。

 楼主| zhuotuzi 发表于 2017-1-28 09:57 | 显示全部楼层
关键的是系统的初始化。
 楼主| zhuotuzi 发表于 2017-1-28 09:57 | 显示全部楼层
如果你配置完发现不能运行,很可能是你忘了开启串口的时钟了。
 楼主| zhuotuzi 发表于 2017-1-28 09:58 | 显示全部楼层
QQ图片20170128095126.jpg
哈哈,这个图不错吧
 楼主| zhuotuzi 发表于 2017-1-28 09:59 | 显示全部楼层
  • extern char GetChar(void);
  • int32_t main(void);
  • void RS485_SendAddressByte(uint8_t u8data);
  • void RS485_SendDataByte(uint8_t *pu8TxBuf, uint32_t u32WriteBytes);
  • void RS485_9bitModeMaster(void);


这几个可以看出这些函数的特征,在编写之前通过预先定义,可以让程序更少的出错。

 楼主| zhuotuzi 发表于 2017-1-28 10:02 | 显示全部楼层
另外这个是收发的是字符,8BIT的,如果是收发16BIT的呢,??怎么做呢?
mintspring 发表于 2017-1-28 10:38 | 显示全部楼层
全面的注释很容易理解这个外设怎么用。
598330983 发表于 2017-1-28 10:48 | 显示全部楼层
硬件流控制

硬件流控制常用的有RTS/CTS流控制和DTR/DSR(数据终端就绪/数据设置就绪)流控制。

硬件流控制必须将相应的电缆线连上,用RTS/CTS(请求发送/清除发送)流控制时,应将通讯两端的RTS、CTS线对应相连,数据终端设备(如计算机)使用RTS来起始调制解调器或其它数据通讯设备的数据流,而数据通讯设备(如调制解调器)则用CTS来起动和暂停来自计算机的数据流。这种硬件握手方式的过程为:我们在编程时根据接收端缓冲区大小设置一个高位标志(可为缓冲区大小的75%)和一个低位标志(可为缓冲区大小的25%),当缓冲区内数据量达到高位时,我们在接收端将CTS线置低电平(送逻辑0),当发送端的程序检测到CTS为低后,就停止发送数据,直到接收端缓冲区的数据量低于低位而将CTS置高电平。RTS则用来标明接收设备有没有准备好接收数据。

常用的流控制还有还有DTR/DSR(数据终端就绪/数据设置就绪)。我们在此不再详述。由于流控制的多样性,我个人认为,当软件里用了流控制时,应做详细的说明,如何接线,如何应用。
598330983 发表于 2017-1-28 10:49 | 显示全部楼层
软件流控制

由于电缆线的限制,我们在普通的控制通讯中一般不用硬件流控制,而用软件流控制。一般通过XON/XOFF来实现软件流控制。常用方法是:当接收端的输入缓冲区内数据量超过设定的高位时,就向数据发送端发出XOFF字符(十进制的19或Control-S,设备编程说明书应该有详细阐述),发送端收到XOFF字符后就立即停止发送数据;当接收端的输入缓冲区内数据量低于设定的低位时,就向数据发送端发出XON字符(十进制的17或Control-Q),发送端收到XON字符后就立即开始发送数据。一般可以从设备配套源程序中找到发送的是什么字符。

应该注意,若传输的是二进制数据,标志字符也有可能在数据流中出现而引起误操作,这是软件流控制的缺陷,而硬件流控制不会有这个问题。
598330983 发表于 2017-1-28 10:50 | 显示全部楼层
  1. /*UART0_Init*/
  2. void UART0_Init()
  3. {

  4.     /* Set P3 multi-function pins for UART0 RXD and TXD */
  5.     SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
  6.     SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0);

  7.     /* Enable UART module clock */
  8.     CLK->APBCLK |= (CLK_APBCLK_UART0_EN_Msk | CLK_APBCLK_UART0_EN_Msk);

  9.     /* Select UART module clock source */
  10.     CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART_S_Msk;
  11.     CLK->CLKSEL1 |= CLK_CLKSEL1_UART_S_HXT;
  12.    
  13.     /* Reset UART IP */
  14.     SYS->IPRSTC2 |=  SYS_IPRSTC2_UART0_RST_Msk;
  15.     SYS->IPRSTC2 &= ~SYS_IPRSTC2_UART0_RST_Msk;

  16.         UART0->FCR |= UART_FCR_RFR_Msk;    /* RX FIFO RESET*/
  17.         UART0->FCR |= UART_FCR_TFR_Msk;    /* TX FIFO RESET*/        
  18.    
  19.     /* Configure UART0 and set UART0 Baudrate */
  20.     UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HXT, 115200);
  21.     UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;   
  22.    
  23. }

  24. void RS485_MODE_Init()
  25. {
  26.    
  27.     /* Set P0 multi-function pins for UART0 RTS */
  28.         SYS->P0_MFP &= ~(SYS_MFP_P03_Msk );
  29.         SYS->P0_MFP |= (SYS_MFP_P03_RTS0 );

  30.    
  31.     /* Select UART RS485 function mode */
  32.     UART0->FUN_SEL = UART_FUNC_SEL_RS485;

  33.          /* Set RX_DIS enable before set RS485-NMM mode */
  34.          UART0->FCR &= ~ UART_FCR_RX_DIS_Msk;  /* Enable RS485 RX */
  35.         //UART0->FCR |= UART_FCR_RX_DIS_Msk;    /* Disable RS485 RX */
  36.                
  37.       /* Set RS485-NMM Mode */
  38.     UART1->ALT_CSR = UART_ALT_CSR_RS485_NMM_Msk;   
  39.                
  40.     /* Set RS485-Master as AUD mode */
  41.     /* Enable AUD mode to HW control RTS pin automatically */
  42.     /* You also can use GPIO to control RTS pin for replacing AUD mode*/
  43.     UART0->ALT_CSR = UART_ALT_CSR_RS485_AUD_Msk;
  44.         
  45.     /* Set Data Format, Only need parity enable whenever parity ODD/EVEN */
  46.          UART0->LCR = (UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1);
  47.         UART0->LCR &= (~UART_PARITY_MARK);


  48.    /* Set RTS pin active level as low level active --*/
  49.             UART0->MCR = UART0->MCR & (~UART_MCR_LEV_RTS_Msk) | UART_RTS_IS_LOW_LEV_ACTIVE;
  50.         //UART0->MCR = UART0->MCR & (~UART_MCR_LEV_RTS_Msk) | UART_RTS_IS_HIGH_LEV_ACTIVE;
  51.    
  52.         
  53.       /* Flush Rx FIFO */
  54.     UART0->FCR |= UART_FCR_RFR_Msk; /* Clear data from RX FIFO */

  55.     /* Set RTS Trigger Level as 1 bytes INT*/
  56.      UART0->FCR = UART0->FCR & (~UART_FCR_RTS_TRI_LEV_Msk) | UART_FCR_RTS_TRI_LEV_1BYTE;

  57.         /* Set RX Trigger Level as 1 bytes INT*/
  58.      UART0->FCR = UART0->FCR & (~UART_FCR_RFITL_Msk) | UART_FCR_RFITL_1BYTE;

  59.     /* Enable CTS autoflow control */
  60.    // UART0->IER |= UART_IER_AUTO_CTS_EN_Msk;
  61.     /* Enable RTS autoflow control */
  62.     UART0->IER |= UART_IER_AUTO_RTS_EN_Msk;
  63.                                          
  64.     /* Enable RDA\RLS\Time-out Interrupt */
  65.     UART0->IER |= UART_IER_RDA_IEN_Msk | UART_IER_RLS_IEN_Msk ;//| UART_IER_RTO_IEN_Msk;

  66.     /* Enable UART0 IRQ */
  67.     NVIC_EnableIRQ(UART0_IRQn);
  68.     }
598330983 发表于 2017-1-28 11:01 | 显示全部楼层
485是半双工模式,RS232全双工模式,支持同时接收发送,而485是单工。流控制都可以即硬件流控,也可软件流控。422是485的升级。

全双工:同一时刻既可发又可收。
半双工:同一时刻不可能既发又收,收发是时分的。
全双工要求:收与发各有单独的信道。可用于实现两个站之间通讯及
星型网,环网。不可用于总线网。
半双工要求:收发可共用同一信道,可用于各种拓扑结构的局域 网络
最常用于总线网。
半双工数据速率理论上是全双工的一半。
598330983 发表于 2017-1-28 11:03 | 显示全部楼层
搞清RS422 与RS485:
RS422 至少分别有一个差分发送口和差分接收口。两节点通讯时,一方的发送口与另一方的接收口相连。
需两对线。
RS422 不能直接用于三电以上的直接互连,当然不能直接用总线连接。
RS485 的差分发送口与自身的差分接收口同相并连,多点间通过 RS485 只需一对线。
RS422 的发送口如与其接收口同相并连,就变成RS485。

3,又于RS422 可接成RS485,所以它们的电气参数必然完全相同。

4,需要说一下,很多人经常把RS232,RS422,RS485 误称为通讯或网络协议,这是很不应该的,其实它
们仅是关于通讯的一个机械和电气接口标准(顶多是网络协议中的物理层面)。
捉虫天师 发表于 2017-1-29 17:08 | 显示全部楼层
通过串口的485模式进行数据的发送和接收
稳稳の幸福 发表于 2017-1-30 08:42 | 显示全部楼层
不是所有的单片机串口支持485,新唐做到了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

218

主题

3445

帖子

7

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