📄 f50x_lin_master.c
字号:
// P1.0 - TX (LIN), Push-Pull, Digital
// P1.1 - RX (LIN), Open-Drain, Digital
// P1.2 - Unassigned, Open-Drain, Digital
// P1.3 - LED, Push-Pull, Digital
// P1.4 - SW1, Open-Drain, Digital
// P1.5 - Unassigned, Open-Drain, Digital
// P1.6 - Unassigned, Open-Drain, Digital
// P1.7 - Unassigned, Open-Drain, Digital
//
//-----------------------------------------------------------------------------
void Port_Init (void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
P1MDOUT = 0x09; // Set P1.0 to push-pull
// Set P1.1 to open-drain
// Set P1.3 to push-pull
// Set P1.4 to open-drain
P0SKIP = 0xFF; // Skip to place LIN on 1.0 and 1.1
XBR2 = 0x41; // Enable LIN, crossbar and weak pullups
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// LIN0_Master_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Intializes the LIN peripheral to master mode.
//
// LIN is an asynchronous, serial communications interface. All LIN registers
// besides the control mode register (LIN0CF) are indirectly accessed;
// the address is specified in the LINADDR register which points to a specific
// data register which can be accessed through the LINDATA register.
// Waveforms and additional specifications can be found in the LIN consortium
// (http:\\www.lin-subbus.com).
//-----------------------------------------------------------------------------
void LIN0_Master_Init (void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
// Enable interface, configure the device for LIN Master, manual baud rate
LIN0CF = 0x80;
LIN0CF |= 0x40;
SFRPAGE = ACTIVE_PAGE;
// Load the least significant byte of the divider.
LIN0ADR = LIN0DIV;
LIN0DAT = (U8) LIN_DIVIDER;
// Load the multiplier, prescalar, and most significant bit of the divider.
LIN0ADR = LIN0MUL;
LIN0DAT = (U8) ((LIN_PRESCALAR << 6) | (LIN_MULTIPLIER << 1)
| (LIN_DIVIDER >> 8));
LIN0ADR = LIN0SIZE;
LIN0DAT = 0x80; // Enhanced checksum
LIN0ADR = LIN0CTRL;
LIN0DAT = 0x0C; // Reset LININT and LIN0ERR
EIE1 |= 0x80; // Enable LIN interrupts
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------
//
// This is the ISR for the PCA0. Module 2 will send a LIN transmit or request
// frame every 20ms to the slave. If there is a falling edge on the master
// switch, meaning that the switch was just pressed, send a LED on transfer.
// If there is a rising edige on the master switch, meaning that the switch
// was just released, send a LED off transfer. If the switch was in the same
// state as it was previously, meaning that the switch is either not pressed
// or is being held down, send a request frame to retreive the status of the
// slave switch.
//
//-----------------------------------------------------------------------------
INTERRUPT (PCA0_ISR, INTERRUPT_PCA0)
{
static U8 sw1prev = 0; // Status of the switch during the last
// interrupt
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = ACTIVE_PAGE;
if (CCF2)
{
CCF2 = 0; // Clear other interrupt flags for PCA
// Interrupt every 20 ms
Next_Interrupt_Time.U16 = Next_Interrupt_Time.U16 + TWENTY_MS;
PCA0CPL2 = Next_Interrupt_Time.U8[LSB];
PCA0CPH2 = Next_Interrupt_Time.U8[MSB];
if ((sw1prev == 0) && (SW1 == 1))
{
// Button was down and switch is now off = rising edge
// Turn off LED
LIN0ADR = LIN0CTRL;
LIN0DAT |= TXRX; // Select to transmit data
LIN0ADR = LIN0ID;
LIN0DAT = ID_LED_SLAVE_OFF; // Tell slave to turn off LED
LIN0ADR = LIN0SIZE;
LIN0DAT = (LIN0DAT & 0xF0) | 0x00; // Transmitting 0 byte
LIN0ADR = LIN0CTRL;
LIN0DAT |= STREQ; // Start Request
}
else if ((sw1prev == 1) && (SW1 == 0))
{
// Button was up and switch is now pressed = falling edge
// Turn on LED
LIN0ADR = LIN0CTRL;
LIN0DAT |= TXRX; // Select to transmit data
LIN0ADR = LIN0ID;
LIN0DAT = ID_LED_SLAVE_ON; // Tell slave to turn on LED
LIN0ADR = LIN0SIZE;
LIN0DAT = (LIN0DAT & 0xF0) | 0x00; // Transmitting 0 byte
LIN0ADR = LIN0CTRL;
LIN0DAT |= STREQ; // Start Request
}
else if ((sw1prev == SW1))
{
// Same state as last state, covers 00 and 11
// Poll slave switch
LIN0ADR = LIN0CTRL;
LIN0DAT &= ~TXRX; // Create a master receive operation
LIN0ADR = LIN0ID;
LIN0DAT = ID_SW1_SLAVE_QUERY; // Want to know status of slave switch
LIN0ADR = LIN0SIZE;
LIN0DAT = (LIN0DAT & 0xF0) | 0x01; // Transmitting 1 byte
LIN0ADR = LIN0CTRL;
LIN0DAT |= STREQ; // Start Request
}
}
else
{
PCA0CN &= ~0xBB; // Clear other PCA interrupt flags
}
sw1prev = SW1; // Save value of switch
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// LIN0_ISR
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This ISR triggers when completing/receiving a transmission from the slave.
// Depending on what message is sent, LED (P1.3) on the slave will turn on/off.
// When receiving a transmission from the slave, the information in data byte
// 1 will tell the master the state of the switch on the slave side. The master
// will then toggle the LED (P1.3) on the master side accordingly.
//
//-----------------------------------------------------------------------------
INTERRUPT (LIN0_ISR, INTERRUPT_LIN0)
{
U8 ctrl, ID, command, status, error;
static U8 num_error = 0;
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = ACTIVE_PAGE;
LIN0ADR = LIN0ST; // Retrieve status
status = LIN0DAT;
LIN0ADR = LIN0CTRL;
ctrl = LIN0DAT;
LIN0ADR = LIN0ID;
ID = LIN0DAT;
if (status & LININTREQ)
{
if (status & ERROR) // If an error was detected
{
LIN0ADR = LIN0ERR;
error = LIN0DAT; // Check the error register
// Keep track of the number of errors received
num_error++;
// Handle your errors here, application dependent
}
else if(status & DONE) // If transmission/reception completed
{
// If in recieve mode and ID is correct
if (((ctrl & TXRX) == 0) && (ID == ID_SW1_SLAVE_QUERY))
{
LIN0ADR = LIN0DT1;
command = LIN0DAT; // Get info from transmission
if (command == LED_MASTER_ON)
{
LED = 1;
}
if (command == LED_MASTER_OFF)
{
LED = 0;
}
}
}
}
LIN0ADR = LIN0CTRL;
LIN0DAT |= 0x0C; // Reset LININT and LIN0ERR
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -