本帖最后由 缥缈九哥 于 2014-10-7 00:18 编辑
利用国庆假期,写了一个简单方案。用了串口FIFO中断和状态机,详情请看源码:
#define DMXBUFMAX 513
typedef enum {dmxIDLE=1,dmxBREAK,dmxSTART,dmxSLOT,dmxTOUT,dmxEND} status_t;
typedef struct
{
status_t status;
uint32_t index;
uint32_t length;
uint8_t slot[DMXBUFMAX];
}dmx_t; dmx_t dmxRx,dmxTx;
/*---------------------------------------------------------------------------------------------------------*/
/* Define functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
void DMX512_Transmit(const uint8_t slot0, const uint32_t address, const uint32_t length);
void DMX_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Reset IP */
SYS_ResetModule(UART0_RST);
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Select UART module clock source */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HXT, CLK_CLKDIV0_UART(1));
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set PD multi-function pins for UART0 RXD(PD.0) and TXD(PD.1) */
// SYS->GPD_MFPL &= ~(SYS_GPD_MFPL_PD0MFP_Msk | SYS_GPD_MFPL_PD1MFP_Msk);
// SYS->GPD_MFPL |= (SYS_GPD_MFPL_PD0MFP_UART0_RXD | SYS_GPD_MFPL_PD1MFP_UART0_TXD);
/* Set PD multi-function pins for UART0 RXD(PD.6) and TXD(PD.1) */
SYS->GPD_MFPL &= ~(SYS_GPD_MFPL_PD6MFP_Msk | SYS_GPD_MFPL_PD1MFP_Msk);
SYS->GPD_MFPL |= (SYS_GPD_MFPL_PD6MFP_UART0_RXD | SYS_GPD_MFPL_PD1MFP_UART0_TXD);
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
UART_Open(UART0, 250000);
/* Set Data Format*/ /* Only need 8 M 2 */
UART_SetLine_Config(UART0, 0, UART_WORD_LEN_8, UART_PARITY_MARK, UART_STOP_BIT_2);
/* Set RX Trigger Level = 14 */
UART0->FIFO = (UART0->FIFO & (~ UART_FIFO_RFITL_Msk)) | UART_FIFO_RFITL_14BYTES;
/* Set Timeout time 16 bit-time */
UART_SetTimeoutCnt(UART0,16);
#if 0
/* Set RTS Trigger Level */
UART0->MODEM |= UART_RTS_IS_HIGH_LEV_TRG;
UART0->FIFO = (UART0->FIFO &~ UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_14BYTES;
/* Enable RTS and CTS autoflow control */
UART0->INTEN |= UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk;
#endif
/* Enable RDA\RLS\RTO Interrupt */
UART_EnableInt(UART0, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RLSIEN_Msk | UART_INTEN_RXTOIEN_Msk));
/* Disable Interrupt */
// UART_DisableInt(UART0, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RLSIEN_Msk | UART_INTEN_RXTOIEN_Msk));
dmxRx.status=dmxIDLE;dmxRx.length=dmxRx.index=0;
/* Lock protected registers */
SYS_LockReg();
}
/*---------------------------------------------------------------------------------------------------------*/
/* ISR to handle UART Channel 0 interrupt event */
/*---------------------------------------------------------------------------------------------------------*/
void UART0_IRQHandler(void)
{
uint32_t u32IntSts=UART0->INTSTS;
if(dmxRx.index>=DMXBUFMAX){dmxRx.index=0;}
if(u32IntSts & UART_INTSTS_RLSINT_Msk) // UART_INTSTS_RLSIF_Msk
{
if(dmxRx.status==dmxIDLE){dmxRx.status=dmxBREAK;}
UART0->FIFOSTS |= UART_FIFOSTS_ADDRDETF_Msk | UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_BIF_Msk;
uint8_t tmp = UART_READ(UART0);
if(dmxRx.status==dmxBREAK){dmxRx.status=dmxSLOT;dmxRx.length=dmxRx.index=0;}
}
if(u32IntSts & UART_INTSTS_RDAINT_Msk) //UART_INTSTS_RDAIF_Msk
{
for(uint32_t i=0;i<13;i++)
{
uint8_t tmp=UART_READ(UART0);
if(dmxRx.status==dmxSLOT){dmxRx.slot[dmxRx.index++]=tmp;}
}
}
if(u32IntSts & UART_INTSTS_RXTOINT_Msk) //UART_INTSTS_RXTOIF_Msk
{
if(dmxRx.status==dmxSLOT){dmxRx.status=dmxTOUT;}
while(UART0->FIFOSTS & UART_FIFOSTS_RXPTR_Msk)
{
uint8_t tmp=UART_READ(UART0);
if(dmxRx.status==dmxTOUT){dmxRx.slot[dmxRx.index++]=tmp;}
}
}
if((dmxRx.status==dmxTOUT)||(dmxRx.index>=DMXBUFMAX))
{dmxRx.length=dmxRx.index;dmxRx.status=dmxEND;dmxRx.index=0;}
if(u32IntSts & UART_INTSTS_THREINT_Msk) // UART_INTSTS_THREIF_Msk
{printf("THRE\n\r");}
}
/*---------------------------------------------------------------------------------------------------------*/
/* DMX512 Transmit */
/*---------------------------------------------------------------------------------------------------------*/
void DMX512_Transmit(const uint8_t slot0, const uint32_t address, const uint32_t length)
{
uint8_t *buf=(uint8_t *)address;uint32_t len=length;
#if 0
UART0->FUNCSEL = UART_FUNCSEL_LIN;
UART0->ALTCTL |= UART_ALTCTL_LINTXEN_Msk;
// UART0->LINCTL &= UART_LINCTL_HSEL_Msk;
// UART0->LINCTL |= (UART_LINCTL_HSEL_Msk & 0x01);
UART0->ALTCTL &= ~UART_ALTCTL_BRKFL_Msk;
UART0->ALTCTL |= (UART_ALTCTL_BRKFL_Msk & 0x0f);
#else
/* DMX512 “SPACE” for BREAK 88us */
UART0->LINE |= UART_LINE_BCB_Msk;
CLK_SysTickDelay(88);
/* DMX512 “MARK” After BREAK (MAB) 8us */
UART0->LINE &= ~UART_LINE_BCB_Msk;
CLK_SysTickDelay(8);
#endif
/* DMX512 START CODE (Slot 0 Data) 1byte */
UART_WRITE(UART0,slot0);
/* DMX512 SLOT 1-512 DATA (Maximum 512) 512 bytes */
UART_Write(UART0,buf,len);
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int dmx512_test(void)
{
uint32_t delay=0;
/* Init System, IP clock and multi-function I/O */
DMX_Init();
DBG_PRINTF("\n\r\n\r");
DBG_PRINTF("*** 9G-NUC451 V3.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
DBG_PRINTF("*** 9G-NUC451 V3.00 Rebooting ...\n\r\n\r");
/*---------------------------------------------------------------------------------------------------------*/
/* SAMPLE CODE */
/*---------------------------------------------------------------------------------------------------------*/
uint8_t buf[512];for(uint32_t i=0;i<sizeof(buf);i++){buf=i>>1;}
// printf("Transmission Test:\n\r");
// while(1) {UART_Write(UART0,buf,sizeof(buf));CLK_SysTickDelay(500000);}
while(1)
{
if(delay>10000)
{
DMX512_Transmit(0,(uint32_t)&buf[0],sizeof(buf));
delay=0;
}
if(dmxRx.status==dmxEND)
{
printf("DMX:");for(uint32_t i=0;i<dmxRx.length;i++){if(i%16==0){printf("\n\r");}printf("%02x ",dmxRx.slot);}
DMX512_Transmit(dmxRx.slot[0],(uint32_t)&dmxRx.slot[1],dmxRx.length-1);
dmxRx.status=dmxIDLE;dmxRx.length=0;
}
CLK_SysTickDelay(100);delay++;
}
} |