Re: SoftUART для PIC

May 06, 2006 0 Replies

 X-Virus-Scanned: amavisd-new at bezeqint.net



Hello, Alexey Belyaev! You wrote in conference fido7.ru.embedded to All on Tue, 28 Mar 2006 22:18:10 +0400:


AB> Мoжeт ecть y кoгo пpocтoй пpимepчик SoftUART для PIC? AB> Интepcyeт тoлкьo 1 линия AB> RX (пpиём инфы из внe co cтopoны МК). AB> Зapaнee cпacибo.



Вот из рабочего проекта надергал, мог чего-то недодергать, но идея ясна. Компилировалось для pic16 и pic18 в качестве второго uart'а.



typedef unsigned char byte;



#define RX_BUF_SIZE 16



static volatile byte rx_smpl_cntr; /* recevier sample counter */ static volatile byte rx_state; /* receiver state (bit number) */ static volatile byte rx_1; /* Rx One counter */ static volatile byte rx_0; /* Rx Zero counter */ static volatile byte rrx; /* receveing data */ static volatile byte tx_smpl_cntr; /* transmitter sample counter */ static volatile byte tx_state; /* transmitter state (bit number) */ static volatile byte txd; /* transmitted data */ static volatile char rx_buf[RX_BUF_SIZE]; /* receiver FIFO buffer */



static volatile byte rb_head; /* receiver FIFO buffer head pointer */ static volatile byte rb_tail; /* receiver FIFO buffer tail pointer */ static volatile bit rb_overlap; /* receiver FIFO buffer overlap flag */ static volatile bit rx_ok; /* 1 - receve complite */ static volatile bit tx_ok; /* 1 - transmit in progress */



void putch(byte c) { while (tx_ok == 1) { idle(); } txd = c; }



int tgetch(void) { int cx = -1;



/* get received byte from the fifo buffer */ if (rb_overlap == 0) /* get before head */ { if (rb_tail < rb_head) { cx = rx_buf[rb_tail]; rb_tail++; } /* else buffer_empty(); */ } else /* get after head */ { if (rb_head <= rb_tail) /* if there is byte(s) in the buffer */ { cx = rx_buf[rb_tail]; rb_tail++; } /* else buffer_empty(); */ if (rb_tail == RX_BUF_SIZE) /* cyling the buffer */ { rb_tail = 0; rb_overlap = 0; } } return cx; }



void interrupt sys_int(void) { volatile static byte __100msc; /* 100ms cyclic counter */ volatile static byte __70us; /* 70us resettable timer */ byte cc;



TMR0 = TMR0INIT + 8; /* Reload timer to 70us period */ T0IF = 0; /* Clear interrupt flag */



if (rx_ok == 0) { rx_smpl_cntr++;



if (TRx == 1) /* One detection */ { if (rx_1 < 255) rx_1++; /* One counter */ } else rx_1 = 0;



if (TRx == 0) /* Zero detection */ { if (rx_0 < 255) rx_0++; /* Zero counter */ } else rx_0 = 0;



if (rx_smpl_cntr == 0) { rx_state = 0; /* restart receiving */ rx_1 = 0; rx_0 = 0; rrx = 0; }



if (rx_state == 0) { rx_state = 1; /* start receiving */ rx_1 = 0; rx_0 = 0; rx_smpl_cntr = 0; rx_ok = 0; }



if ((rx_state == 1) && (rx_0 > 1) && (rx_smpl_cntr > 1)) { rx_state = 2; /* start bit detected */ rx_1 = 0; rx_0 = 0; rx_smpl_cntr = 0; }



/* data bits receiving */ if ((rx_state > 1) && (rx_state < 10) && (rx_smpl_cntr == 3)) { rx_state++; rrx >>= 1; if (rx_1 > 1) { rrx |= 0x80; /* Tst = 1; */ } rx_1 = 0; rx_0 = 0; rx_smpl_cntr = 0; }



if ((rx_state == 10) && (rx_smpl_cntr == 3)) /* stop bit detection */ { if (rx_1 > 1) { /* put received byte to fifo buffer */ if (rb_overlap == 0) /* put after tail */ { rx_buf[rb_head] = rrx; rb_head++; if (rb_head == RX_BUF_SIZE) /* cyling the buffer */ { rb_head = 0; rb_overlap = 1; } } else /* put before tail */ { if (rb_head < rb_tail) /* if thre is room for byte */ { rx_buf[rb_head] = rrx; rb_head++; } /* else buffer_full(); */ } } rx_state = 0; rx_1 = 0; rx_0 = 0; rx_smpl_cntr = 0; } }


/* mportb - PORTB mirror, MTx - Tx pin mask */ if (tx_ok == 1) { /* Start bit */ if ((tx_state == 0) && (tx_smpl_cntr == 1)) { /* TTx = 0; */ mportb &= ~MTx; }



/* data bits */ if ((tx_state > 0) && (tx_state < 9) && (tx_smpl_cntr == 1)) { if ((txd & 1) == 0) { /* TTx = 0; */ mportb &= ~MTx; } else { /* TTx = 1; */ mportb |= MTx; } txd >>= 1; }



/* first stop bit */ if ((tx_state == 9) && (tx_smpl_cntr == 1)) { /* TTx = 1; */ mportb |= MTx; }



/* second stop bit */ if ((tx_state == 11) && (tx_smpl_cntr == 1)) { /* TTx = 1; */ mportb |= MTx; tx_state = 0; tx_smpl_cntr = 0; tx_ok = 0; }



tx_smpl_cntr++; if (tx_smpl_cntr == 3) { tx_state++; tx_smpl_cntr = 0; } } else { /* keep Tx high after transmition */ tx_state = 0; tx_smpl_cntr = 0; /* TTx = 1; */ mportb |= MTx; }



}


dima

formatting link


Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required