Nu stressar jag kanske med den här frågan, men jag har problem med att få min mjukvaru-flödeskontroll att fungera. När jag kommenterara bort XON och XOFF kommandona i koden flyter det bra så länge inte mottagarbuffern blir fylld. Med XON/XOFF kommandona fryser mitt C# program ett tag för att sedan visa input som t ex:
Servo position: 0x84
Servo po position: 0xD0
Servo position: 0xCC
Servo position: 0xC2
Servo position: 0xBC
Servo position: 0xB8
Servo position: 0xB1
Servo position: 0xAB
Servo position: 0sition: 0x7C
Servo position: 0x20
Servo position: 0x26
Servo position: 0x3A
Servo position: 0x5B
Servo po position: 0x79
Servo position: 0xCD
Frysningen uppkommer när XOFF skickas. Det verkar som om datorprogrammet även slutar att lyssna när ett XOFF-tecken anländer.
Här kommer en rejäl bit med PIC-kod. Jag vet dock inte om det verkligen är på PIC'en problemet ligger. Serieportsrutinen i mitt PC program är standardklassen i .NET så den borde ju fungera klanderfritt.
Kod: Markera allt
//***************************************************************************************
// Config
//***************************************************************************************
#pragma chip PIC16F877A
// Used in Stdio.c
#define Clock_4MHz
#pragma origin 4
//***************************************************************************************
// Constants
//***************************************************************************************
// USART buffer sizes
#define RC_BUFFER_SIZE 80
// USART buffer low/hight levels (flow control)
#define RC_BUFFER_LOW 5
#define RC_BUFFER_HIGH 60
// Software flow control characters
#define XON 0x11
#define XOFF 0x13
// Servo control
#define LONG_DELAY 100
#define LONG_DELAY_CNT 4
#define OFFSET_DELAY -70
// Finite state machine states
#define LONG_DELAY_STATE 0
#define OFFSET_DELAY_STATE 1
#define POSITION_DELAY_STATE 2
// PC <-> uC control commands
#define CMD_RESET 0x00
#define CMD_SET_SERVO 0x20
#define CMD_LED1 0x21
//***************************************************************************************
// Variables
//***************************************************************************************
// Interrupt state saving
uns8 FSRTemp;
// Hardware pins
bit debugLed @ PORTB.1;
bit servoPin @ PORTB.2;
// USART buffers
#pragma rambank 1
char rcBuffer[RC_BUFFER_SIZE];
#pragma rambank -
// USART buffer info
bit sendXOff;
uns8 rcStart;
uns8 rcLength;
// Used to time TMR0 correctly into a good control pulse
uns8 servoState;
uns8 servoDelay;
uns8 longDelayCnt;
//***************************************************************************************
// Function Prototypes
//***************************************************************************************
void SendXOn();
void SendXOff();
uns8 UsartRead();
void UsartWrite(uns8 data);
void UsartPrintf(const char *nate, int16 my_byte);
//***************************************************************************************
// Interrupt Service Routine
//***************************************************************************************
#include <int16CXX.h>
interrupt int_server( void)
{
int_save_registers // W, STATUS (and PCLATH)
FSRTemp = FSR;
if (T0IF) // TMR0 interrupt
{
// Long delay just ended
if (servoState == LONG_DELAY_STATE)
{
longDelayCnt--;
if (longDelayCnt == 0)
{
servoState = OFFSET_DELAY_STATE;
TMR0 = OFFSET_DELAY;
servoPin = 1;
}
else
{
// Since long delay is 0, this is totally unneccesary.
TMR0 = LONG_DELAY;
}
}
else if (servoState == OFFSET_DELAY_STATE)
{
servoState = POSITION_DELAY_STATE;
TMR0 = servoDelay;
}
else
{
servoState = LONG_DELAY_STATE;
longDelayCnt = LONG_DELAY_CNT;
TMR0 = LONG_DELAY;
servoPin = 0;
}
T0IF = 0; /* reset flag */
}
if (RCIF && RCIE) // USART receive interrupt
{
if (OERR) // Buffer overrun
{
CREN = 0; // Clear error flag
CREN = 1;
}
else if (FERR) // Framing error
{
rcStart = 0;
rcLength = 1;
rcBuffer[0] = RCREG;
}
else
{
if (rcLength < RC_BUFFER_SIZE)
{
uns8 offset = rcStart + rcLength;
if (offset >= RC_BUFFER_SIZE)
offset -= RC_BUFFER_SIZE;
rcBuffer[offset] = RCREG;
rcLength++;
}
if (rcLength == RC_BUFFER_HIGH)
{
sendXOff = 1;
}
}
}
FSR = FSRTemp;
int_restore_registers // W, STATUS (and PCLATH)
}
//***************************************************************************************
// Send XON software flow control character
//***************************************************************************************
void SendXOn()
{
UsartWrite(XON);
}
//***************************************************************************************
// Send XOFF software flow control character
//***************************************************************************************
void SendXOff()
{
UsartWrite(XOFF);
}
//***************************************************************************************
// Buffered USART read
//***************************************************************************************
uns8 UsartRead()
{
if (rcLength == 0)
return 0xff;
uns8 data = rcBuffer[rcStart];
rcStart++;
rcLength--;
if (rcStart >= RC_BUFFER_SIZE)
rcStart = 0;
if (rcLength == RC_BUFFER_LOW)
SendXOn();
return data;
}
//***************************************************************************************
// Unbuffered USART write (blocking)
//***************************************************************************************
void UsartWrite(uns8 data)
{
while (TXIF == 0);
TXREG = data;
}
//***************************************************************************************
// Binary to hex (Copyright SparkFunElectronics)
//***************************************************************************************
//Returns ASCII Decimal and Hex values
uns8 bin2Hex(char x)
{
skip(x);
#pragma return[16] = "0123456789ABCDEF"
}
//***************************************************************************************
// Formatted USART write (Copyright SparkFunElectronics)
//***************************************************************************************
//Prints a string including variables
void UsartPrintf(const char *nate, int16 my_byte)
{
uns8 i, k, m, temp;
uns8 high_byte = 0, low_byte = 0;
uns8 y, z;
uns8 decimal_output[5];
for(i = 0 ; ; i++)
{
k = nate[i];
if (k == '\0')
break;
else if (k == '%') //Print var
{
i++;
k = nate[i];
if (k == '\0')
break;
else if (k == '\\') //Print special characters
{
i++;
k = nate[i];
UsartWrite(k);
} //End Special Characters
else if (k == 'b') //Print Binary
{
for( m = 0 ; m < 8 ; m++ )
{
if (my_byte.7 == 1) UsartWrite('1');
if (my_byte.7 == 0) UsartWrite('0');
if (m == 3) UsartWrite(' ');
my_byte = my_byte << 1;
}
} //End Binary
else if (k == 'd') //Print Decimal
{
//Divide number by a series of 10s
for(m = 4 ; my_byte > 0 ; m--)
{
temp = my_byte % (uns16)10;
decimal_output[m] = temp;
my_byte = my_byte / (uns16)10;
}
for(m++ ; m < 5 ; m++)
UsartWrite(bin2Hex(decimal_output[m]));
} //End Decimal
else if (k == 'h') //Print Hex
{
//New trick 3-15-04
UsartWrite('0');
UsartWrite('x');
if(my_byte > 0x00FF)
{
UsartWrite(bin2Hex(my_byte.high8 >> 4));
UsartWrite(bin2Hex(my_byte.high8 & 0b.0000.1111));
}
UsartWrite(bin2Hex(my_byte.low8 >> 4));
UsartWrite(bin2Hex(my_byte.low8 & 0b.0000.1111));
} //End Hex
else if (k == 'f') //Print Float
{
UsartWrite('!');
} //End Float
else if (k == 'u') //Print Direct Character
{
//All ascii characters below 20 are special and screwy characters
//if(my_byte > 20)
UsartWrite(my_byte);
} //End Direct
} //End Special Chars
else
UsartWrite(k);
}
}
//***************************************************************************************
// OnSetServo command handler
// param: 0x00 -> 0xff
// Position of servo axis
//***************************************************************************************
void OnSetServo(uns8 param)
{
servoDelay = 255 - param;
UsartPrintf("Servo position: %h\n", param);
}
//***************************************************************************************
// OnLed1 command handler
// param: 0x00 or 0x01
// Led on/off
//***************************************************************************************
void OnLed1(uns8 param)
{
if (param == 0)
debugLed = 0;
else
debugLed = 1;
UsartPrintf("LED1 state: %h\n", param);
}
//***************************************************************************************
// Application initialization
//***************************************************************************************
void init()
{
PORTC = 0b.0000.0000;
TRISC = 0b.1000.0000; //0 = Output, 1 = Input RC7 - Incoming Data RX
TRISB = 0b.0000.0000;
SPBRG = 25; //4MHz for 9600 baud rate
TXSTA = 0b.0010.0100; //8-bit asych mode, high speed uart enabled
RCSTA = 0b.1001.0000; //Serial port enable, 8-bit asych continous receive mode
OPTION = 0b.0000.0010; // TMR0 prescaler divide by 8
T0IE = 1; // Enable TMR0 interrupt
RCIE = 1; // Enable USART RC interrupt
TXIE = 0; // Disable USART TX interrupt
GIE = 1;
// RS-232 software flow control status
sendXOff = 0;
rcStart = 0;
rcLength = 0;
// Servo control
servoState = LONG_DELAY_STATE;
longDelayCnt = LONG_DELAY_CNT;
TMR0 = LONG_DELAY;
debugLed = 1;
}
//***************************************************************************************
// Application Entry Point
//***************************************************************************************
void main()
{
init();
uns8 command;
uns8 param;
bit waitingForCommand = 1;
while (1)
{
if (sendXOff)
{
SendXOff();
sendXOff = 0;
}
if (rcLength > 0)
{
if (waitingForCommand)
{
command = UsartRead();
waitingForCommand = 0;
switch (command)
{
case CMD_RESET:
// Reset is sent 3 times. Just keep looking for commands.
waitingForCommand = 1;
break;
case CMD_SET_SERVO:
case CMD_LED1:
break;
default:
// If the program runs to this position the command was invalid. Continue to wait for a valid one.
waitingForCommand = 1;
UsartPrintf("Unknown command: %h\n", command);
break;
}
}
else
{
param = UsartRead();
waitingForCommand = 1;
switch (command)
{
case CMD_SET_SERVO:
OnSetServo(param);
break;
case CMD_LED1:
OnLed1(param);
break;
}
}
}
}
}