📄 int232.c
字号:
//****************************************************************************
// intserial.c
// V1.00
//
// These are interrupt and timer driven serial routines.
// Uses the Interrupt input pin and Timer0 overflow interrupt etc.
//
// The received data is double buffered to hopefully limit overflows
//
// Author: Michael Pearce
// Chemistry Department, University of Canterbury
//
// Started: Monday 3 May 1999
//
//****************************************************************************
// Version Information
//****************************************************************************
// Version 1.00 - 03 May 1999
// Start of the project.
//****************************************************************************
#include <conio.h>
#define DEBUG
//********** Define the PORTS and TRIS to use ***********
// Change to Suit your requirements
static bit RXDPin @ (unsigned)&PORTB*8+0; /* bit0 in port B */
static bit RXDTris @ (unsigned)&TRISB*8+0; /* bit0 in port B */
static bit TXDPin @ (unsigned)&PORTB*8+1; /* bit1 port B */
static bit TXDTris @ (unsigned)&TRISB*8+1; /* bit1 in port B */
#ifdef DEBUG
static bit TestPin @ (unsigned)&PORTB*8+7; /* Test PIN port A 0 */
static bit TestTris @ (unsigned)&TRISB*8+7;
static bit TestPin1 @ (unsigned)&PORTB*8+6; /* Test PIN port A 0 */
static bit TestTris1 @ (unsigned)&TRISB*8+6;
static bit TestPin2 @ (unsigned)&PORTB*8+5; /* Test PIN port A 0 */
static bit TestTris2 @ (unsigned)&TRISB*8+5;
#endif
//********** Define the Baud Rate to use ***********
// Requires PIC_XTAL to be defined (The Crystal Frequecy being used in MHz)
// Maximum and minimum baud rates depend on the crystal frequency used
// Here is a list of what rates should work - tested bauds marked with *
// These are calculated using a OVERSAMPLE of 8 - it may be possible to
// increase of decrease the range by changing the oversample to help but do not
// recommend going less than a 6 times oversample.
// Maximum Speeds calculated by no less than 10 timer ticks (before overhead)
// This may not leave much processor time due to minimum times taken
// by interrupt routine to check things.
//
// XTAL BAUD RATES TESTED
//---------------------------------------------------------------------
// 2MHz 300,600,1200,2400,4800 NONE
// 4MHz 600,1200,2400,4800,9600 NONE
// 8MHz 1200,2400,4800,9600,19200 NONE
// 10MHz 2400,4800,9600,19200 NONE
// 12MHz 2400,4800,9600,19200 NONE
// 16MHz 2400,4800,9600,19200,38400 NONE
// 20MHz 4800,9600,19200,38400,56000 NONE
//--------------------------------------------------------------------
#define BAUD 9600 //-- The Baud Rate Required
#define OVERSAMPLE 8 //-- Samples per bit - Even Nus only
#define OVERHEAD (2+2) //-- 2 Timer cycles + Interrupt cycles
#if (OVERSAMPLE-1)&OVERSAMPLE
#error OVERSAMPLE value must be a power of 2
#endif
// 1,000,000 / BAUD = us per bit Time
// Divide by us per instruction cycle to give the cycles per bit time
// Divide by number of ticks per sample time
#define TIMERTICKS ( ( (1000000/BAUD) * (PIC_CLK/4 ) ) / (OVERSAMPLE-1) )
//#define TIMERTICKS (PIC_CLK*1000000) / (4 * BAUD * OVERSAMPLE)
// Subtract Timer ticks from the overflow value then add the overhead
// Hopefully this is the correct time for what you want
#if (TIMERTICKS > 0xFC)
#error ######### BAUDRATE NOT POSSIBLE - TO SLOW OR UNDERFLOWED ########
#error # Possible Solutions:
#error # Choose a faster Baud Rate
#error # Use a lower frequency Crystal/Clock
#error # Increase the OVERSAMPLE Rate to suit
#endif
#if (TIMERTICKS < 0x0A)
#error ######### BAUDRATE NOT POSSIBLE - TO FAST OR OVERFLOWED ########
#error # Possible Solutions:
#error # Choose Slower Baud Rate
#error # Use a Higher frequency Crystal/Clock
#error # Lower the OVERSAMPLE Rate to suit
#endif
//#define TIMERRELOAD (unsigned char) ((0xFF-TIMERTICKS)+2)
#define TIMERRELOAD 0xFF - TIMERTICKS + OVERHEAD
//********** Define the Flags, Data Etc ***********
bit RxdNewData=0; //-- Indicated new data has been received
bit RxdOverflow=0; //-- Indicates data recieved before buffer cleared
bit RxdReceiving=0; //-- Indicated New data being read in
bit RxdStartOK=0; //-- Indicates Valid Start Bit found
bit TxdInProgress=0; //-- Indicates that data is being transmitted
bit SerialIntEnabled=0; //-- Enables/Disables the Interrupt serial routine
bit DataOverflow=0; //-- Indicates data overflow to user
char SerialTxdCount; //-- Bit count for transmitted data
char SerialTxdDivider; //-- Timer Divider for transmitted data
char SerialRxdCount; //-- Bit count for received data
char SerialRxdDivider; //-- Timer Divider for Recieved data
char RXDBuffer; //-- Recieved data temp buffer
char RXDData; //-- Recieved data buffer
char TXDData; //-- Transmit data buffer
//****************************************************************************
// FUNCTION DEFINITIONS
//****************************************************************************
void InitUart(void);
void SerialEnable(void);
void SerialDisable(void);
//****************************************************************************
// InitUart
// Initialises the serial port bits and sets up and starts the timer
//****************************************************************************
void InitUart(void)
{
#ifdef DEBUG
TestTris=0;
TestTris1=0;
TestTris2=0;
#endif
RBPU=0; //-- Enable pull ups on Port B
TXDPin=1; //-- Transmit pin initially High
TXDTris=0; //-- and set to output
RXDTris=1; //-- RXD pin set as input
SerialEnable(); //-- Setup the interrupts etc
}
//********************* END OF InitUart
//****************************************************************************
// SerialEnable
// Enables the serial interrupt routine and configures the timer for serial
// timing.
//****************************************************************************
void SerialEnable(void)
{
INTEDG=0; //-- Rxd pin Interrupt on FALLING Edge
PSA=1; //-- Prescaler set for WDT
T0CS=0; //-- Timer Increment on INTERNAL clock
TMR0=TIMERRELOAD; //-- Load the timer
SerialIntEnabled=1; //-- Enable the serial interrupt routines
INTE=1; //-- Enable external interrupt
T0IE=1; //-- Enable the timer interrupt
GIE=1; //-- Enable the Global interrupt Enable
}
//********************* END OF SerialEnable
//****************************************************************************
// SerialDisable
// Disables the serial interrupt routine - but leaves timer running
//****************************************************************************
void SerialDisable(void)
{
SerialIntEnabled=0;
}
//********************* END OF SerialDisable
//****************************************************************************
// SerialDisableAll
// Disables the serial interrupt routine and STOPS the timer
//****************************************************************************
void SerialDisableAll(void)
{
SerialIntEnabled=0; //-- Disable the timer interrupt
T0IE=0;
}
//********************* END OF SerialDisableAll
//****************************************************************************
// SerialInterrupt
//****************************************************************************
interrupt void SerialInterrupt(void)
{
if(SerialIntEnabled)
{
//########## TIMER ZERO OVERFLOW INTERRUPT #############
if(T0IF)
{
#ifdef DEBUG
TestPin ^= 1; //-- Toggle Test pin
#endif
TMR0=TIMERRELOAD; //-- Reload the Timer
T0IF=0; //-- Clear the interrupt flag
//########## RECIEVE DATA ############
if(RxdReceiving) //-- Receive the data in ????
{
if( (SerialRxdDivider--)==0)
{
#ifdef DEBUG
TestPin2=RXDPin;
#endif
SerialRxdDivider=OVERSAMPLE; //-- Reload the counter
SerialRxdCount--;
if(SerialRxdCount==9)
{
//-- Check for Start Bit
if(RXDPin)
{
RxdReceiving=0; //-- Bad Start Bit!!! Cancel the Run!!!!
INTE=1;
}
}
else
{
if(SerialRxdCount)
{
#ifdef DEBUG
TestPin1 = RXDPin;
#endif
//-- read in data bit
RXDBuffer >> 1;
if(RXDPin)
{
RXDBuffer |= 0x80; //-- Set the bit
}
else
{
RXDBuffer &=0x7F; //-- Clear the bit
}
}
else
{
//-- Check for Stop Bit
if(RXDPin)
{
//-valid stop signal
RxdReceiving=0;
RXDData=RXDBuffer;
if(!RxdNewData)
{
RxdNewData=1; //-- New Data has arrived
}
else
{
RxdOverflow=1; //-- Data has overflowed - latest data in buffer
}
INTE=1;
}
else
{
//-- NOT A VALID STOP SIGNAL - TRASH THE DATA
RxdReceiving=0; //-- BAD DATA - CANCEL THE RUN
INTE=1;
}
}
}
}
}
if(TxdInProgress) //-- Sending data out ????
{
if((--SerialTxdDivider)==0)
{
SerialTxdDivider=OVERSAMPLE;
SerialTxdCount--;
if(SerialTxdCount==9)
{
//-- Start Bit --
TXDPin=0;
}
else
{
if(SerialTxdCount)
{
//-- Send Data Bit--
if(TXDData & 0x01)
{
TXDPin=1;
}
else
{
TXDPin=0;
}
TXDData=TXDData >>1; //-- Point to next data bit
}
else
{
//-- Stop Bit --
TXDPin=1;
TxdInProgress=0;
}
}
}
}
}
//########## END OF TIMER ZERO OVERFLOW INTERRUPT #############
if(INTF) //-- START OF NEW SERIAL BYTE ????
{
INTE=0; //-- Disable interrupt until Receive complete
INTF=0; //-- Clear the interrupt Flag
RxdReceiving=1; //-- Indicate Receiving new Data
SerialRxdCount=10; //-- # of Bits to read in
SerialRxdDivider=OVERSAMPLE/2; //-- First time to sample Start Bit (1/2)
}
}
//else
//{
//********** Add Serial OFF Interrupt routines here **********
//}
}
//********************* END OF SerialInterrupt
//****************************************************************************
// putch
//****************************************************************************
void putch(char c)
{
while(TxdInProgress); //-- Wait for data to be sent ---> Should have timeout in here!!!
TXDData=c; //-- copy data to the output buffer
SerialTxdCount=10; //-- # of Bits to transmit
SerialTxdDivider=OVERSAMPLE; //-- Initial divider - to allow for a stop bit!!!
TxdInProgress=1; //-- Transmit is now in progress
}
//********************* END OF putch
//****************************************************************************
// getch
//****************************************************************************
char getch(void)
{
char c;
while(!RxdNewData); //-- Wait for new data to arrive
c=RXDData; //-- Copy data from buffer
RxdNewData=0; //-- Clear the New Data Flag
if(RxdOverflow) //-- Check if an Overflow occured
{
DataOverflow=1; //-- Indicate the overflow - cleared by programmer
RxdOverflow=0; //-- Clear the overflow flag
}
return(c); //-- Return the data
}
//********************* END OF getch
//****************************************************************************
//
//****************************************************************************
//********************* END OF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -