⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opexserial.c

📁 学完单片机就要使用实时系统在单片机上运行
💻 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 + -