/****************************************************************************
* @file main.c
* @version V1.00
* $Revision: 7 $
* $Date: 14/01/29 2:05p $
* @brief M051 Series UART Interface Controller Driver Sample Code
*
* @note
* Copyright (C) 2011 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"
#define PLL_CLOCK 50000000
#define IS_USE_RS485NMM 0 //1:Select NMM_Mode , 0:Select AAD_Mode
#define MATCH_ADDRSS1 0xC0
#define MATCH_ADDRSS2 0xA2
#define UNMATCH_ADDRSS1 0xB1
#define UNMATCH_ADDRSS2 0xD3
/*---------------------------------------------------------------------------------------------------------*/
/* Define functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
extern char GetChar(void);
int32_t main(void);
void RS485_HANDLE(void);
void RS485_9bitModeSlave(void);
/*---------------------------------------------------------------------------------------------------------*/
/* ISR to handle UART Channel 0 interrupt event */
/*---------------------------------------------------------------------------------------------------------*/
void UART1_IRQHandler(void)
{
RS485_HANDLE();
}
/*---------------------------------------------------------------------------------------------------------*/
/* RS485 Callback function */
/*---------------------------------------------------------------------------------------------------------*/
void RS485_HANDLE()
{
volatile uint32_t addr = 0;
volatile uint32_t u32IntSts = UART1->ISR;
/* RLS INT & RDA INT */ //For RS485 Detect Address
if((u32IntSts & UART_ISR_RLS_INT_Msk) && (u32IntSts & UART_ISR_RDA_INT_Msk))
{
if(UART1->FSR & UART_FSR_RS485_ADD_DETF_Msk) /* ADD_IF, RS485 mode */
{
addr = UART1->RBR;
UART_RS485_CLEAR_ADDR_FLAG(UART1); /* clear ADD_IF flag */
printf("\nAddr=0x%x,Get:", addr);
#if (IS_USE_RS485NMM ==1) //RS485_NMM
/* if address match, enable RX to receive data, otherwise to disable RX */
/* In NMM mode, user can decide multi-address filter */
/* In AAD mode, only one address can set */
if((addr == MATCH_ADDRSS1) || (addr == MATCH_ADDRSS2))
{
UART1->FCR &= ~ UART_FCR_RX_DIS_Msk; /* Enable RS485 RX */
}
else
{
printf("\n");
UART1->FCR |= UART_FCR_RX_DIS_Msk; /* Disable RS485 RX */
UART1->FCR |= UART_FCR_RFR_Msk; /* Clear data from RX FIFO */
}
#endif
}
}
else if((u32IntSts & UART_ISR_RDA_INT_Msk) || (u32IntSts & UART_ISR_TOUT_INT_Msk)) /* Rx Ready or Time-out INT*/
{
/* Handle received data */
printf("%d,", UART1->RBR);
}
else if(u32IntSts & UART_ISR_BUF_ERR_INT_Msk) /* Buffer Error INT */
{
printf("\nBuffer Error...\n");
UART_ClearIntFlag(UART1, UART_ISR_BUF_ERR_INT_Msk);
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* RS485 Receive Test (IS_USE_RS485NMM: 0:AAD 1:NMM) */
/*---------------------------------------------------------------------------------------------------------*/
void RS485_9bitModeSlave()
{
printf("\n");
printf("+-----------------------------------------------------------+\n");
printf("| Pin Configure |\n");
printf("+-----------------------------------------------------------+\n");
printf("| _______ _______ |\n");
printf("| | | | | |\n");
printf("| |Master |---TXD1(P1.3) <====> RXD1(P1.2)---| Slave | |\n");
printf("| | |---RTS1(P0.1) <====> RTS1(P0.1)---| | |\n");
printf("| |_______| |_______| |\n");
printf("| |\n");
printf("+-----------------------------------------------------------+\n");
printf("| RS485 Function Test (9-bit Slave) |\n");
printf("+-----------------------------------------------------------+\n");
/*
The sample code is used to test RS485 9-bit mode and needs
two Module test board to complete the test.
Master:
1.Set AUD mode and HW will control RTS pin. LEV_RTS is set to '0'.
2.Master will send four different address with 10 bytes data to test Slave.
3.Address bytes : the parity bit should be '1'. (Set UA_LCR = 0x2B)
4.Data bytes : the parity bit should be '0'. (Set UA_LCR = 0x3B)
5.RTS pin is low in idle state. When master is sending,
RTS pin will be pull high.
Slave:
1.Set AAD and AUD mode firstly. LEV_RTS is set to '0'.
2.The received byte, parity bit is '1' , is considered "ADDRESS".
3.The received byte, parity bit is '0' , is considered "DATA". (Default)
4.AAD: The slave will ignore any data until ADDRESS match ADDR_MATCH value.
When RLS and RDA interrupt is happened,it means the ADDRESS is received.
Check if RS485_ADD_DETF is set and read UA_RBR to clear ADDRESS stored in rx_fifo.
NMM: The slave will ignore data byte until disable RX_DIS.
When RLS and RDA interrupt is happened,it means the ADDRESS is received.
Check the ADDRESS is match or not by user in UART_IRQHandler.
If the ADDRESS is match,clear RX_DIS bit to receive data byte.
If the ADDRESS is not match,set RX_DIS bit to avoid data byte stored in FIFO.
*/
/* Set Data Format, Only need parity enable whenever parity ODD/EVEN */
UART_SetLine_Config(UART1, 0, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1);
/* Set RTS pin active level as low level active */
UART1->MCR &= ~UART_MCR_LEV_RTS_Msk;
UART1->MCR |= UART_RTS_IS_LOW_LEV_ACTIVE;
#if(IS_USE_RS485NMM == 1)
printf("\n");
printf("+-----------------------------------------------------------+\n");
printf("| Normal Multidrop Operation Mode |\n");
printf("+-----------------------------------------------------------+\n");
printf("| The function is used to test 9-bit slave mode. |\n");
printf("| Only Address %x and %x,data can receive |\n", MATCH_ADDRSS1, MATCH_ADDRSS2);
printf("+-----------------------------------------------------------+\n");
/* Set RX_DIS enable before set RS485-NMM mode */
UART1->FCR |= UART_FCR_RX_DIS_Msk;
/* Set RS485-NMM Mode */
UART_SelectRS485Mode(UART1, UART_ALT_CSR_RS485_NMM_Msk | UART_ALT_CSR_RS485_AUD_Msk, 0);
/* Set RS485 address detection enable */
UART1->ALT_CSR |= UART_ALT_CSR_RS485_ADD_EN_Msk;
#else
printf("Auto Address Match Operation Mode\n");
printf("+-----------------------------------------------------------+\n");
printf("| The function is used to test 9-bit slave mode. |\n");
printf("| Auto Address Match Operation Mode |\n");
printf("+-----------------------------------------------------------+\n");
printf("|Only Address %x,data can receive |\n", MATCH_ADDRSS1);
printf("+-----------------------------------------------------------+\n");
/* Set RS485-AAD Mode and address match is 0xC0 */
UART_SelectRS485Mode(UART1, UART_ALT_CSR_RS485_AAD_Msk | UART_ALT_CSR_RS485_AUD_Msk, MATCH_ADDRSS1);
/* Set RS485 address detection enable */
UART1->ALT_CSR |= UART_ALT_CSR_RS485_ADD_EN_Msk;
#endif
/* Enable RDA\RLS\Time-out Interrupt */
UART_ENABLE_INT(UART1, (UART_IER_RDA_IEN_Msk | UART_IER_RLS_IEN_Msk | UART_IER_RTO_IEN_Msk));
/* Enable UART1 IRQ */
NVIC_EnableIRQ(UART1_IRQn);
printf("Ready to receive data...(Press any key to stop test)\n");
GetChar();
/* Flush Rx FIFO */
UART1->FCR |= UART_FCR_RFR_Msk;
/* Disable RDA\RLS\Time-out Interrupt */
UART_DISABLE_INT(UART1, (UART_IER_RDA_IEN_Msk | UART_IER_RLS_IEN_Msk | UART_IER_RTO_IEN_Msk));
printf("\nEnd test\n");
}
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable Internal RC 22.1184MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
/* Waiting for Internal RC clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
/* Enable external XTAL 12MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);
/* Waiting for external XTAL clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
/* Set core clock as PLL_CLOCK from PLL */
CLK_SetCoreClock(PLL_CLOCK);
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(UART1_MODULE);
/* Select UART module clock source */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));
CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set P3 multi-function pins for UART0 RXD and TXD */
SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0);
/* Set P1 multi-function pins for UART1 RXD and TXD */
SYS->P1_MFP &= ~(SYS_MFP_P12_Msk | SYS_MFP_P13_Msk);
SYS->P1_MFP |= (SYS_MFP_P12_RXD1 | SYS_MFP_P13_TXD1);
/* Set P0 multi-function pins for UART1 RTS */
SYS->P0_MFP = SYS->P0_MFP & (~SYS_MFP_P01_Msk) | SYS_MFP_P01_RTS1;
}
void UART0_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset UART0 module */
SYS_ResetModule(UART0_RST);
/* Configure UART0 and set UART0 Baudrate */
UART_Open(UART0, 115200);
}
void UART1_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset UART1 module */
SYS_ResetModule(UART1_RST);
/* Configure UART1 and set UART1 Baudrate */
UART_Open(UART1, 115200);
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Lock protected registers */
SYS_LockReg();
/* Init UART0 for printf */
UART0_Init();
/* Init UART1 for testing */
UART1_Init();
/*---------------------------------------------------------------------------------------------------------*/
/* SAMPLE CODE */
/*---------------------------------------------------------------------------------------------------------*/
printf("\n\nCPU @ %dHz\n", SystemCoreClock);
printf("\n\nUART Sample Program\n");
/* UART RS485 sample slave function */
RS485_9bitModeSlave();
}