📄 opexserial.c
字号:
//OPEXserial.c
//// (C) 2004 Steve Childress stevech@san.rr.com
#include "OPEX.h"
#define com_BUFSIZERX 64
#define com_BUFSIZETX 255
void com__init(void); // in AVR_Dependent
int num_com_blocks;
unsigned char com_ErrorFlags, com__nl;
unsigned char *com_InBufpr, *com_InBufpw, com_InBuf[com_BUFSIZERX];
unsigned char *com_OutBufpr, *com_OutBufpw, com_OutBuf[com_BUFSIZETX];
unsigned volatile char last_ch_rx;
unsigned volatile int com_InBufCount, com_OutBufCount;
void OPEX_com_init(void)
{
com_OutBufCount = com_InBufCount = com__nl = 0;
com_InBufpw = com_InBufpr = com_InBuf;
com_OutBufpr = com_OutBufpw = com_OutBuf;
serial_init(); // <<<< Change if com_
}
/////////////////////////////////////////////
// return number of chars waiting in the receive buffer
// return either the first or last in the buffer
int OPEX_peek(char *c, BYTE last) // c is the buffer
{
BYTE n;
cli();
if ((n = com_InBufCount) != 0) {
if (c != NULL) {
if (last)
*c = last_ch_rx; // read the last-in character
else
*c = *com_InBufpr; // read the first-in character
}
}
sei();
return((int)n);
}
/////////////////////////////////////////////
// return number of unused bytes in the tx buffer
int OPEX_txbuf_unused(void)
{
return (sizeof(com_OutBuf) - (int) com_OutBufCount); // is one byt
}
/////////////////////////////////////////////
// return number of unused bytes in the tx buffer
int OPEX_txbuf_used(void)
{
return ( (int) com_OutBufCount); // is one byt
}
/////////////////////////////////////////////
// non-queued get string, store in passed buffer.
// Ignores \n. Stops on \r which is not placed in the null-terminated buffer.
// if 2nd argument is non-zero, and if that many seconds expires, return.
// Returns number of chars in buffer. Can be zero if just a \r was received.
// Returns -1 if timeout and no chars placed in buffer.
int OPEX_gets(char *p1, int maxchars, BYTE timeout_secs) // timeout 0 means no timeout
{
char *p;
BYTE n;
BYTE timer = timeout_secs;
p = p1;
while (maxchars != 0) { // loop until end of string or timeout
// loop to get next char, with timeout
n = time.second;
timer = timeout_secs; // reset timer
while (OPEX_getc(p) == 0) { // loop to get and store char using pointer
if (timeout_secs != 0) // if timer is used...
if (n != time.second) { // if one second has elapsed...
if (--timer == 0) // if timed out...
goto gets9; // end the outer while loop
n = time.second;
}
}
if (*p == '\n') // ignore these
continue;
if (*p++ == '\r') { // stop on receipt of this
break; // exit the outer while loop
}
}
gets9:
*p = 0; // terminate the string
if ( (timeout_secs != 0) && (timer == 0) )
return (((p-p1) != 0) ? (int)(p-p1) : -1); // timed out
return((int)(p-p1)); // did not timeout, return strlen
}
//********* com_ RECEIVE PROCESSING ************
// Function returns 0 if no data is available
// else returns non-Zero, and char is stored via pointer
int OPEX_getc(unsigned char *p)
{
if(com_InBufCount == 0)
return(0);
else {
if (p != NULL)
*p = *com_InBufpr;
if(++com_InBufpr == &com_InBuf[sizeof(com_InBuf)])
com_InBufpr = com_InBuf;
cli();
--com_InBufCount; // ISR increments this, so make atomic
sei();
}
return(1);
}
/////////////////////////////////////////////
// serial Receive Interrupt. Called by SIGNAL service in user program.
// store every received byte.
// If an ASCII CR is received, notify the scheduler.
// While the application is receiving binary data, it should probably not have
// a wait for OPEX_sched_FLAGBIT_com_RECEIVED_CR flag posted.
//
void OPEX_com_rx_ISR(BYTE c) // called by ISR
{
last_ch_rx = c;
if(com_InBufCount == sizeof(com_InBuf)) {
com_ErrorFlags |= 1; // buffer overflow error
}
else {
++com_InBufCount;
*com_InBufpw = last_ch_rx; // stored char for peek()
if(++com_InBufpw == &com_InBuf[sizeof(com_InBuf)]) // ring buffer
com_InBufpw = com_InBuf;
// activate any tasks waiting on arrival of the CR character
if (last_ch_rx == '\r')
OPEX_sched_change_flag((BYTE *)&OPEX_sched_flags, OPEX_sched_FLAGBIT_SERIAL_RECEIVED_CR, 1); // flag pointer, bit no, state
// activate any tasks waiting on arrival of any character (runs first)
OPEX_sched_change_flag((BYTE *)&OPEX_sched_flags, OPEX_sched_FLAGBIT_SERIAL_RECEIVED_ANY, 1); // flag pointer, bit no, state
}
}
//////////////////////////////////////////////////////////////
//********* com_ TRANSMIT PROCESSING ************
///////////////////////////////////////
// Send a string from RAM
void OPEX_puts(char *p)
{
while(*p)
OPEX_putc(*p++);
}
///////////////////////////////////////////
// send CR LF
void OPEX_nl(void)
{
OPEX_putc('\r');
OPEX_putc('\n');
}
///////////////////////////////////////
// Send a string from RAM with CRLF
void OPEX_putline(char *s)
{
OPEX_puts(s);
OPEX_nl();
}
///////////////////////////////////////
// Send a string from program memory
void OPEX_puts_P(char *p)
{
char ch;
while((ch = PRG_RDB(p++)) != 0) // null terminated string
OPEX_putc(ch);
}
///////////////////////////////////////
// Send a string from program memory with CRLF
void OPEX_putline_P(char *s)
{
OPEX_puts_P(s);
OPEX_nl();
}
///////////////////////////////////////
// com_ send byte buffered, non-interrupt level code
int OPEX_putcNoBlock(BYTE); // declaration
///////////////////////////////////////
// send char, loop if buffer is full
void OPEX_putc(BYTE c)
{
if (OPEX_putcNoBlock(c) != 0) { // retry if buffer full
++num_com_blocks; // Tally buffer full for statistics
while(OPEX_putcNoBlock(c) != 0) // loop until ISR empties up space
;
}
}
///////////////////////////////////////
// com_ send byte buffered, non-interrupt level code
// Function returns 1 if data cannot be sent, buffer full
// Implements a ring buffer
/////////////////////////////////////////
// Non-Interrupt code
int OPEX_putcNoBlock(BYTE c)
{
int n;
cli();
n = (int)com_OutBufCount;
sei();
if(n == sizeof(com_OutBuf))
return(1); // buffer is full
if (serial_get_txIE() == 0) { // TX data reg empty interrupt enabled?
serial_tx_put(c); // no, so it's TX is idle. output data
serial_change_txIE(1); // TX data reg empty interrupt enable
}
else { // TX is busy, queue data
*com_OutBufpw++ = c;
if(com_OutBufpw == &com_OutBuf[sizeof(com_OutBuf)])
com_OutBufpw = com_OutBuf;
cli();
++com_OutBufCount; // make atomic with the ISR
sei();
}
return(0);
}
////////////////////////////////////
// Tansmit interrupt processing. Called by SIGNAL service in user program.
//
void OPEX_com_tx_ISR(void) // transmit register empty ISR calls this
{
if (com_OutBufCount == 0)
serial_change_txIE(0); // no more interrupts
else {
--com_OutBufCount;
serial_tx_put(*com_OutBufpr++);
if(com_OutBufpr == &com_OutBuf[sizeof(com_OutBuf)])
com_OutBufpr = com_OutBuf;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -