diff options
Diffstat (limited to 'rs422lib/rsbus.c')
-rw-r--r-- | rs422lib/rsbus.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/rs422lib/rsbus.c b/rs422lib/rsbus.c new file mode 100644 index 0000000..705736f --- /dev/null +++ b/rs422lib/rsbus.c @@ -0,0 +1,201 @@ +/*
+ * rsbus.c
+ *
+ * Created on: 2014-4-26
+ * Author: Tuowen
+ */
+#include "rsbus.h"
+#include "sysctl.h"
+
+#define SYSRET (0xF0)
+#define INSREP (0x0F)
+
+unsigned char rs_rxbuf[RSMAX];
+unsigned char len;
+unsigned char pch;
+unsigned char ret;
+rshdlr rxhdlr;
+enum rs_stat{REST,ST,ADDR,READ,DISCARD,ED,DED};
+enum rs_stat rs_st=REST;
+
+unsigned char rs_tx[12]={STBIT1,0,RSADDR,MACTYPE,0,0,0,0,0,0,0,0};
+unsigned char tx_len;
+unsigned char tx_pos;
+
+#pragma vector=USCIAB0TX_VECTOR
+__interrupt void USCI0TX_ISR(void)
+{
+ if (tx_pos == tx_len) // TX over?
+ {
+ UC0IE &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt
+ RSOUT &= ~(RSPIN);
+ }
+ else
+ UCA0TXBUF = rs_tx[tx_pos++]; // TX next character
+}
+
+#pragma vector=USCIAB0RX_VECTOR
+__interrupt void rsbus_rx(void)
+{
+ //IFG2&=(~UCA0RXIFG);
+ int dat;
+ dat=UCA0RXBUF;
+ /************ Simple State Machine *************/
+ switch (rs_st)
+ {
+ case REST:
+ rs_st=(dat==STBIT0)?ST:REST;
+ break;
+ case ST:
+ rs_st=(dat==STBIT1)?ADDR:REST;
+ break;
+ case ADDR:
+ if (dat==RSADDR)
+ {
+ rs_st=READ;
+ len=0;
+ pch=RSADDR;
+ }
+ else
+ rs_st=DISCARD;
+ break;
+ case READ:
+ rs_rxbuf[len++]=dat;
+ pch^=dat;
+ if (dat==EDBIT0)
+ rs_st=ED;
+ if (len>=RSMAX)
+ rs_st=REST;
+ break;
+ case DISCARD:
+ if (dat==EDBIT0)
+ rs_st=DED;
+ break;
+ case DED:
+ if (dat==EDBIT1)
+ rs_st=REST;
+ else
+ rs_st=DISCARD;
+ break;
+ case ED:
+ if (dat==EDBIT1)
+ {
+ rs_st=REST;
+ --len;
+ pch^=EDBIT0;
+ if (pch==0) // Parity check passed
+ {
+ if (len<2)
+ {
+ ret=(SYSRET ^ MACTYPE);
+ SYSCALL_IRQ(RSSYSRET); // RETURN machine type
+ }
+ else
+ SYSCALL_IRQ(RSSYSBIT); // SYSCTL call happened here!!!
+ }
+ else
+ {
+ ret=(SYSRET ^ INSREP);
+ SYSCALL_IRQ(RSSYSRET); // RETURN machine type
+ }
+ }
+ else
+ {
+ rs_rxbuf[len++]=dat;
+ pch^=dat;
+ rs_st=READ;
+ if (len>=RSMAX)
+ rs_st=REST;
+ }
+ break;
+ }
+ /*//This is a repeater
+ if (IFG2&UCA0TXIFG)
+ UCA0TXBUF=dat;*/
+}
+
+void rsbus_w(int addr,unsigned char* buf,unsigned int len)
+{
+ unsigned int i;
+ if (len>4)
+ return;
+ RSOUT |= RSPIN;
+ tx_len=len+7;
+ unsigned int parity=addr^MACTYPE^RSADDR;
+ rs_tx[1]=addr;
+ for (i=0;i<len;++i)
+ parity^=(rs_tx[4+i]=buf[i]);
+ rs_tx[4+len]=parity;
+ rs_tx[5+len]=EDBIT0;
+ rs_tx[6+len]=EDBIT1;
+ tx_pos=0;
+ UCA0TXBUF=(STBIT0 & 0xff);
+ UC0IE |= UCA0TXIE;
+}
+
+/*void rsbus_w(int addr,char* buf,int len)
+{
+ // Acquire output
+ RSOUT |= RSPIN;
+ delay_ms(2);
+ unsigned int i=0;
+ unsigned int parity=addr^RSADDR;
+ // Start bits
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(STBIT0 & 0xff);
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(STBIT1 & 0xff);
+ // Addr
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(addr & 0xff);
+ // RSADDR
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(RSADDR & 0xff);
+ // Data
+ while (i<len)
+ {
+ parity^=buf[i];
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=buf[i++];
+ }
+ // Parity bit
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(parity & 0xff);
+ // End bits
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(EDBIT0 & 0xff);
+ while ((IFG2&UCA0TXIFG) == 0);
+ UCA0TXBUF=(EDBIT1 & 0xff);
+ while ((IFG2&UCA0TXIFG) == 0);
+ // Release output
+ RSOUT &= ~(RSPIN);
+}*/
+
+void rsbus_syscall()
+{
+ rxhdlr(rs_rxbuf,len-1);
+}
+
+void rsbus_ret()
+{
+ rsbus_w(0,(unsigned char*)&ret,1);
+}
+
+void rsbus_init(rshdlr hdlr) // If need to change this part consult user guide pg908
+{
+ P1SEL |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
+ P1SEL2 |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
+ UCA0CTL1 |= UCSSEL_2; // UartCLK: SMCLK=4MHz
+ UCA0BR0 = 208; // BaudRate: 19200
+ UCA0BR1 = 0; // BaudRate: 19200
+ UCA0MCTL = UCBRS0 + UCBRS1; // Modulation UCBRSx = 3
+ UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
+ IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
+ /******************* CTL for output buffer ***********************/
+ RSDIR |= RSPIN;
+ RSOUT &= ~(RSPIN); //HIGH for ENABLE -> Low as DEFAULT
+ /******************* SYSCTL INIT *************************/
+ rxhdlr=hdlr;
+ sysctl_reghdlr(RSSYSBIT,&rsbus_syscall);
+ sysctl_reghdlr(RSSYSRET,&rsbus_ret);
+}
|