📄 main.c
字号:
/************************************************************
Copyright (C) 1995-2002 Pumpkin, Inc. and its
Licensor(s). Freely distributable.
$Source: C:\\RCS\\D\\salvo\\demo\\d5\\main.c,v $
$Author: aek $
$Revision: 1.15 $
$Date: 2001-09-27 10:24:21-07 $
Demo program. Runs on Microchip PICDEM-2 (PIC16C77,
PIC16F877, PIC18C452, etc.) and MPLAB-ICD (PIC16F877).
Implements quad full-duplex 1200bps UARTs in software.
Requires Salvo v2.3.0 or higher.
************************************************************/
#ifndef MAIN_C_INCLUDES
#define MAIN_C_INCLUDES
#include "d5.h"
#include "main.h"
#include "salvo.h"
/************************************************************
**** ****
** **
Global variable declarations.
** **
**** ****
************************************************************/
/* current value of character being shifted out by s/w */
/* UART. Cannot be banked because PutTxNChar() expects */
/* non-banked parameter. */
/* state of transmitter state machine (runs in ISR). */
/* xmitter status is used to control which xmitters are */
/* currently running. */
/* buffer control blocks for transmitters. */
/* ring buffers for transmitters. */
#if TRANSMITTERS >= 1
unsigned char tx1Data;
LOC_INT_LOCALS unsigned char txState;
LOC_INT_LOCALS struct {
unsigned char tx1Active:1;
unsigned char tx2Active:1;
unsigned char tx3Active:1;
unsigned char tx4Active:1;
} txStatus;
LOC_BCB typeBcb txBcbArray[TRANSMITTERS];
LOC_BUFF typeBuff tx1Buff[TX1_BUFF_SIZE];
#endif
#if TRANSMITTERS >= 2
unsigned char tx2Data;
LOC_BUFF typeBuff tx2Buff[TX2_BUFF_SIZE];
#endif
#if TRANSMITTERS >= 3
unsigned char tx3Data;
LOC_BUFF typeBuff tx3Buff[TX3_BUFF_SIZE];
#endif
#if TRANSMITTERS >= 4
unsigned char tx4Data;
LOC_BUFF typeBuff tx4Buff[TX4_BUFF_SIZE];
#endif
/* receiver status is used to control which receivers */
/* are running and also to flag rx errors. */
/* rx timestamps are used to mark when the bitstream's */
/* start bit goes low. In current value of TMR1. */
/* buffer control blocks for receivers. */
/* ring buffers for receivers. */
#if RECEIVERS >= 1
LOC_INT_LOCALS unsigned int rx1Timestamp;
LOC_INT_LOCALS struct {
unsigned char rx1Error:1;
unsigned char rx2Error:1;
unsigned char rx3Error:1;
unsigned char rx4Error:1;
unsigned char rx1Active:1;
unsigned char rx2Active:1;
unsigned char rx3Active:1;
unsigned char rx4Active:1;
} rxStatus;
LOC_BCB typeBcb rxBcbArray[RECEIVERS];
LOC_BUFF typeBuff rx1Buff[RX1_BUFF_SIZE];
#endif
#if RECEIVERS >= 2
LOC_INT_LOCALS unsigned int rx2Timestamp;
LOC_BUFF typeBuff rx2Buff[RX2_BUFF_SIZE];
#endif
#if RECEIVERS >= 3
LOC_INT_LOCALS unsigned int rx3Timestamp;
LOC_BUFF typeBuff rx3Buff[RX3_BUFF_SIZE];
#endif
#if RECEIVERS >= 4
LOC_INT_LOCALS unsigned int rx4Timestamp;
LOC_BUFF typeBuff rx4Buff[RX4_BUFF_SIZE];
#endif
/* control vars and ring buffers for RX5/TX5: built-in */
/* UART. We use explicit vars instead of control */
/* blocks because GetRx5Buff() and PutRx5Buff() are */
/* different from GetBuff() and PutBuff() due */
/* to interrupts. */
LOC_RX5 unsigned char rx5Count;
LOC_RX5 unsigned char rx5InP, rx5OutP;
LOC_RX5 unsigned char rx5Buff[RX5_BUFF_SIZE];
LOC_TX5 unsigned char tx5Count;
LOC_TX5 unsigned char tx5InP, tx5OutP;
LOC_TX5 unsigned char tx5Buff[TX5_BUFF_SIZE];
/* local function declarations. */
#if ENABLE_TEST_CODE
void TestCode(void);
#if RUN_TEST_CODE_TASK
void TaskTestCode(void);
#endif
#endif
/* context-switching labels. */
_OSLabel(TaskTestCode1)
/************************************************************
**** ****
** **
main()
Initialize relevant hardware registers, initialize Salvo and
create tasks (idle task is created automatically), enable
interrupts and start multitasking.
IMPORTANT NOTE: Since PICC (stackless) compiler is used,
background calls to OSSignalBinSem() must be protected,
since it's also called in the foreground.
** **
**** ****
************************************************************/
int main( void )
{
/* some test systems need this. */
InitTestHardware();
#if ENABLE_TEST_PINS
/* setup test port. */
InitTestPins();
#endif
/* initialize the port we'll be bit-banging. */
InitUARTTris();
InitUARTPort();
/* configure TMR1 for 1:1 prescale, use internal */
/* clock. TMR1 is used to count instruction */
/* cycles. Note that TMR1CS is 0, and will remain */
/* unchanged. */
T1CON = 0b00000001;
/* initialize RS-232 transmitter software. */
InitUART();
/* set TMR2 for 1:8 postcale. TMR2 is used to call */
/* the Salvo system timer every quarter bit */
/* period. */
PR2 = TMR2_RELOAD;
T2CON = 0b00111100;
/* initialize global flags. */
#if RECEIVERS >= 1
rxStatus.rx1Error = 0;
rxStatus.rx2Error = 0;
rxStatus.rx3Error = 0;
rxStatus.rx4Error = 0;
rxStatus.rx1Active = 0;
rxStatus.rx2Active = 0;
rxStatus.rx3Active = 0;
rxStatus.rx4Active = 0;
#endif
#if TRANSMITTERS >= 1
txState = TXSTATE_IDLE;
txStatus.tx1Active = 0;
txStatus.tx2Active = 0;
txStatus.tx3Active = 0;
txStatus.tx4Active = 0;
#endif
/* initialize Salvo. */
OSInit();
/* create tasks. */
#if TRANSMITTERS >= 1
OSCreateTask(TaskTx, TASKTX_P, TASKTX_PRIO);
#endif
#if RECEIVERS >= 1
OSCreateTask(TaskRx1, TASKRX1_P, TASKRX1_PRIO);
#endif
#if ENABLE_TEST_CODE && RUN_TEST_CODE_TASK
OSCreateTask(TaskTestCode, TASKTESTCODE_P, TASKTESTCODE_PRIO);
#endif
/* these tasks will work only with the standard */
/* libraries, since the freeware libraries support */
/* only 3 tasks. */
#if RECEIVERS >= 2
OSCreateTask(TaskRx2, TASKRX2_P, TASKRX2_PRIO);
#endif
#if RECEIVERS >= 3
OSCreateTask(TaskRx3, TASKRX3_P, TASKRX3_PRIO);
#endif
#if RECEIVERS >= 4
OSCreateTask(TaskRx4, TASKRX4_P, TASKRX4_PRIO);
#endif
/* transmit buffers are initially empty. */
#if TRANSMITTERS >= 1
OSCreateBinSem(BINSEM_TXBUFF_P, 0);
OSCreateBinSem(BINSEM_TXDONE_P, 0);
OSCreateBinSem(BINSEM_TXSTART_P, 0);
#endif
/* enable TMR2 interrupts, enable peripheral */
/* interrupts, enable (global) interrupts. */
TMR2IE = 1;
PEIE = 1;
ei();
/* start multitasking. */
for (;;) {
OSSched();
#if ENABLE_TEST_CODE && !RUN_TEST_CODE_TASK
TestCode();
#endif
}
}
/************************************************************
**** ****
** **
TestCode()
Test code -- feed each transmit buffer with permuted data.
Since each receiver is listening to its associated
transmitter, undo the permutation and send the data back
out the hardware UART. Test pin marks how long this op takes
and when we're in here.
OSSignalBinSem() must be protected for use with stackless
compilers because it's also called from within ISR().
** **
**** ****
************************************************************/
#if ENABLE_TEST_CODE
void TestCode( void )
{
unsigned char data;
ToggleTPMain();
#if TRANSMITTERS >= 1
if ( GetRx5Buff(&data) == TRUE ) {
if ( PutTx1Buff(data)) {
OSProtect();
OSSignalBinSem(BINSEM_TXBUFF_P);
OSUnprotect();
}
#if TRANSMITTERS >= 2
if ( PutTx2Buff(~data) ) {
OSProtect();
OSSignalBinSem(BINSEM_TXBUFF_P);
OSUnprotect();
}
#endif
#if TRANSMITTERS >= 3
if ( PutTx3Buff((data << 4) | (data >> 4)) ) {
OSProtect();
OSSignalBinSem(BINSEM_TXBUFF_P);
OSUnprotect();
}
#endif
#if TRANSMITTERS >= 4
if ( PutTx4Buff(~((data << 4) | (data >> 4))) ) {
OSProtect();
OSSignalBinSem(BINSEM_TXBUFF_P);
OSUnprotect();
}
#endif
}
#endif /* #if TRANSMITTERS >= 1 */
#if RECEIVERS >= 1
if ( GetRx1Buff(&data) == TRUE )
PutTx5Buff(data);
#endif
#if RECEIVERS >= 2
if ( GetRx2Buff(&data) == TRUE )
PutTx5Buff(~data);
#endif
#if RECEIVERS >= 3
if ( GetRx3Buff(&data) == TRUE )
PutTx5Buff((data << 4) | (data >> 4));
#endif
#if RECEIVERS >= 4
if ( GetRx4Buff(&data) == TRUE )
PutTx5Buff(~((data << 4) | (data >> 4)));
#endif
ToggleTPMain();
}
#endif
/************************************************************
**** ****
** **
TaskTestCode()
Run test code as a task. Return to scheduler when done.
** **
**** ****
************************************************************/
#if ENABLE_TEST_CODE && RUN_TEST_CODE_TASK
void TaskTestCode( void )
{
for (;;) {
TestCode();
OS_Yield(TaskTestCode1);
}
}
#endif
/************************************************************
**** ****
** **
InitUART()
Initialize the hardware UART as a 9600bps UART. This UART
has two ring buffers for receive and transmit.
** **
**** ****
************************************************************/
void InitUART( void )
{
/* reset Tx ring buffer pointers. */
tx5Count = 0;
tx5InP = 0;
tx5OutP = 0;
rx5Count = 0;
rx5InP = 0;
rx5OutP = 0;
/* PORTC is output on pin 6, rest is input. */
/* Set Tx out high to avoid bad chars. */
PORTC |= 0x40; /* 01000000 */
TRISC |= 0x80; /* 10000000 */
TRISC &= 0xBF; /* 10111111 */
/* Serial Port is ON, 8-bit data reception, */
/* continuous receive. */
RCSTA = 0x90; /* 10x1xxxx */
/* force Tx ints off now to avoid spurious */
/* outgoing chars when transmitter is enabled. */
TXIE = 0;
/* 8-bit transmit, Tx enabled, Async, BRGH=1 */
TXSTA = 0x24; /* x010x100 */
/* 9600 baud. */
SPBRG = XTAL/16/9600-1;
}
/************************************************************
**** ****
** **
GetRx5Buff(dataP)
Removes a character (if present) from the hardware UART's
receiver ring buffer and copies it to variable specified.
Interrupt control is required because PutRx5Buff() is in
ISR.
Returns: TRUE if a character was present.
FALSE if buffer was empty.
** **
**** ****
************************************************************/
unsigned char GetRx5Buff( unsigned char * dataP )
{
if ( rx5Count ) {
*dataP = rx5Buff[rx5OutP++];
if ( rx5OutP > RX5_BUFF_SIZE-1 )
rx5OutP = 0;
di();
rx5Count--;
ei();
return TRUE;
}
else
return FALSE;
}
/************************************************************
**** ****
** **
PutTx5Buff(data)
Puts the character into the hardware UART's xmitter
ring buffer if room is available.
Interrupt control is required because GetTx5Buff() is in
ISR.
Returns: TRUE on if there was room in buffer.
FALSE if buffer was full.
** **
**** ****
************************************************************/
unsigned char PutTx5Buff(unsigned char data)
{
if ( tx5Count < TX5_BUFF_SIZE )
{
tx5Buff[tx5InP++] = data;
if ( tx5InP > TX5_BUFF_SIZE-1 )
tx5InP = 0;
di();
tx5Count++;
ei();
return TRUE;
}
else
return FALSE;
}
/************************************************************
**** ****
** **
OSIdlingHook()
Not used.
** **
**** ****
************************************************************/
void OSIdlingHook( void )
{
;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -