程序说明:
处理器:PIC18F66K80系列
系统频率:32M (外部晶振8M,4倍频得到)
缓冲器:接收缓冲器0,接受滤波器0,发送缓冲器0
源文件
/*********************************************************************
*
* Includes
*
*********************************************************************/
#include "bsp.h"
/*********************************************************************
*
* Defines
*
*********************************************************************/
// ECAN bitrate define, only can choose one rate
#define F_ECAN_100 0 // 1 set ECAN module on 100Kbps
#define F_ECAN_125 0 // 1 set ECAN module on 125Kbps
#define F_ECAN_500 1 // 1 set ECAN module on 500Kbps
#define F_ECAN_1000 0 // 1 set ECAN module on 1Mbps
/*********************************************************************
*
* Global Variables
*
*********************************************************************/
/* 定义全局变量 */
CanTxMsg g_tCanTxMsg; /* 用于发送 */
CanRxMsg g_tCanRxMsg; /* 用于接收 */
/*********************************************************************
*
* Function: Initialize the CAN Module
*
*********************************************************************/
void ECAN_Init(void)
{
CAN_STB_SetDigitalOutput();//CAN收发器待机模式端配置为输出
CAN_TX_SetDigitalOutput();
CAN_RX_SetDigitalInput();
// Place CAN module in configuration mode, see CANCON register data
CANCON = 0x80; //REQOP bits <2:0> = 0b100
// while(!(CANSTATbits.OPMODE ==0x04)); //Wait for op-mode bits in the
while(CANSTAT != 0X80); //CANSTAT register to = 0b100
//to indicate config mode OK
// Enter CAN module into Mode 0, standard legacy mode; see ECANCON register
ECANCON = 0x00;
// See Microchip application note AN754, Understanding Microchip's
// CAN Module Bit Timing." See also: Microchip Controller Area Network
//(CAN) Bit Timing Calculator, available at Intrepid Control Systems:
//www.intrepidcs.com/support/mbtime.htm.
// Initialize CAN Bus bit rate timing. Assumes only four standard rates.
// Initialize CAN Timing
if (F_ECAN_100==1)
{
// 100 Kbps @ 32MHz
BRGCON1 = 0x13; //SJW=1TQ BRP 19
BRGCON2 = 0x90; //SEG2PHTS 1 sampled once PS1=3TQ PropagationT 1TQ
BRGCON3 = 0x02; //PS2 3TQ
}
else if (F_ECAN_125==1)
{
// 125 Kbps @ 32MHz
BRGCON1 = 0x0F; //SJW=1TQ BRP 15
BRGCON2 = 0x90; //SEG2PHTS 1 sampled once PS1=3TQ PropagationT 1TQ
BRGCON3 = 0x02; //PS2 3TQ
}
else if (F_ECAN_500==1)
{
// 125 Kbps @ 32MHz
BRGCON1 = 0x03; //SJW=1TQ BRP 3
BRGCON2 = 0x90; //SEG2PHTS 1 sampled once PS1=3TQ PropagationT 1TQ
BRGCON3 = 0x02; //PS2 3TQ
}
else if (F_ECAN_1000==1)
{
// 1000 Kbps @ 32MHz
BRGCON1 = 0x01; //SJW=1TQ BRP 1
BRGCON2 = 0x90; //SEG2PHTS 1 sampled once PS1=3TQ PropagationT 1TQ
BRGCON3 = 0x02; //PS2 3TQ
}
// Initialize Receive Masks, see registers RXMxEIDH, RXMxEIDL, etc...
// Mask 0 (M0) will accept NO extended addresses, but any standard address
RXM0EIDH = 0x00; // Extended Address receive acceptance mask, high byte
RXM0EIDL = 0x00; // Extended Address receive acceptance mask, low byte
RXM0SIDH = 0xFF; // Standard Address receive acceptance mask, high byte
RXM0SIDL = 0xE0; // Standard Address receive acceptance mask, low byte
// Mode 0 allows use of receiver filters RXF0 through RXF5. Enable filters
// RXF0 and RXF1, all others disabled. See register RXFCONn.
// Only using two filters
RXFCON0 = 0x01; //Enable Filter-0; disable others
RXFCON1 = 0x00; //Disable Filters 8 through 15
// Initialize Receive Filters
// Filter 0 = 0x312
RXF0EIDH = 0x00; //Extended Address Filter-0 unused, set high byte to 0
RXF0EIDL = 0x00; //Extended Address Filter-0 unused, set low byte to 0
RXF0SIDH = (uint8_t)(0x312>>3); //Standard Address Filter-0 high byte set to xx
RXF0SIDL = (uint8_t)(0x312<<5)&0xE0; //Standard Address Filter-0 low byte set to xx
TXB0CON=0X03;//TXB0为最高优先级3
// After configuring CAN module with above settings, return it
// to Normal mode
CANCON = 0x00;
// while(CANSTATbits.OPMODE!=0x00); //Wait for op-mode bits in the
while(CANSTAT != 0X00); //CANSTAT register to = 0b000
//to indicate Normal mode OK
RXB0CON = 0x20;//只接收有效的标准标识符信息
/* 初始化CAN的中断,PIR5为CAN的外围中断标志寄存器 */
PIR5=0X00; // 清所有CAN中断标志
PIE5bits.RXB0IE = 1; //使能接收缓冲器0的接收中断
IPR5bits.RXB0IP = 1; // 接收缓冲器0的接收中断为高优先级
// PIR5bits.WAKIF = 0; //清除CAN总线活动唤醒中断标志
// PIE5bits.WAKIE = 1; //允许CAN总线活动唤醒中断
// IPR5bits.WAKIP = 1; //CAN总线活动唤醒中断为高优先级
}
/*
*********************************************************************************************************
* 函 数 名: CAN_SetMode
* 功能说明: 配置CAN收发器模式
* 形 参:mode 0,正常模式 1,待机模式
* 返 回 值: 无
*********************************************************************************************************
*/
void CAN_SetMode(uint8_t mode)
{
if(mode == 0)
{
CAN_STB_SetLow();
}
else
{
CAN_STB_SetHigh();
}
}
/*********************************************************************
*
* Function: Check the buffers to determine if they have messages
* if so, transfer the info to the temporary-storage
* variables. Note: Messages to receiver 0 or 1 get saved in
* the same variables. This id done for simplicity in
* this example. You could save messages to separate
* variables, or in separate arrays, if you wish.
*
*********************************************************************/
void ECAN_Receive(CanRxMsg* RxMessage)
{
if (RXB0CONbits.RXFUL) // Check RXB0CON bit RXFUL to see if RX Buffer 0
// has received a message, if so, get the
// associated data from the buffer and save it.
{
/* Get the Id */
RxMessage->IDE = RXB0SIDLbits.EXID;
if (RxMessage->IDE == CAN_Id_Standard)
{
RxMessage->StdId = (uint16_t)RXB0SIDH<<3 | (RXB0SIDL>>5);
}
else
{
}
RxMessage->RTR = RXB0DLCbits.RXRTR;
/* Get the DLC */
RxMessage->DLC = RXB0DLC&0x0F;
/* Get the FMI */
// RxMessage->FMI = 0x00;
/* Get the data field */
RxMessage->Data[0] = RXB0D0;
RxMessage->Data[1] = RXB0D1;
RxMessage->Data[2] = RXB0D2;
RxMessage->Data[3] = RXB0D3;
RxMessage->Data[4] = RXB0D4;
RxMessage->Data[5] = RXB0D5;
RxMessage->Data[6] = RXB0D6;
RxMessage->Data[7] = RXB0D7;
RXB0CONbits.RXFUL = 0; // Reset buffer-0-full bit to show "empty"
}
}
/*
*********************************************************************************************************
* 函 数 名: ECAN_Transmit
* 功能说明: CAN发送报文消息
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void ECAN_Transmit(CanTxMsg* TxMessage)
{
TXB0CONbits.TXREQ = 0; /* 关发送 ,该位发送成功则自动清零*/
if (TxMessage->IDE == CAN_Id_Standard)
{
TXB0SIDH = (uint8_t)(TxMessage->StdId>>3);
TXB0SIDL = (uint8_t)(TxMessage->StdId<<5)&0xE0;
TXB0SIDLbits.EXIDE = TxMessage->IDE;
TXB0DLCbits.TXRTR = TxMessage->RTR;
}
else
{
// TXB0EIDH = TxMessage->ExtId>>8;
// TXB0EIDL = TxMessage->ExtId;
}
TXB0DLC = TxMessage->DLC;
TXB0D0 = TxMessage->Data[0];
TXB0D1 = TxMessage->Data[1];
TXB0D2 = TxMessage->Data[2];
TXB0D3 = TxMessage->Data[3];
TXB0D4 = TxMessage->Data[4];
TXB0D5 = TxMessage->Data[5];
TXB0D6 = TxMessage->Data[6];
TXB0D7 = TxMessage->Data[7];
TXB0CONbits.TXREQ = 1; //Set the buffer to transmit
//while(TXB0CONbits.TXREQ==1); //等待发送 完成
}
void interrupt high_priority High_ISR(void)
{
if(PIR5bits.WAKIF==1)//CAN总线活动唤醒中断
{
PIR5bits.WAKIF = 0;
}
if(PIR5bits.RXB0IF==1)//接收缓冲区0接收到报文
{
PIR5bits.RXB0IF=0; // 清接收中断标志
ECAN_Receive(&g_tCanRxMsg);
if ((g_tCanRxMsg.StdId == 0x312) && (g_tCanRxMsg.IDE == CAN_ID_STD) && (g_tCanRxMsg.DLC == 0x08))
{
// 用户自定义
}
}
}
头文件
/*
* File: eacn.h
* Author: Administrator
*
* Created on 2017年7月11日, 下午4:33
*/
#ifndef ECAN_H
#define ECAN_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief CAN Tx message structure definition
*/
#define CAN_Id_Standard 0X00 /*!< Standard Id */
#define CAN_Id_Extended 0X01 /*!< Extended Id */
#define CAN_RTR_Data 0X00 /*!< Data frame */
#define CAN_RTR_Remote 0X01 /*!< Remote frame */
#define CAN_ID_STD CAN_Id_Standard
#define CAN_ID_EXT CAN_Id_Extended
#define CAN_RTR_DATA CAN_RTR_Data
#define CAN_RTR_REMOTE CAN_RTR_Remote
#define CAN_MODE_NORMAL 0 //CAN收发器正常模式
#define CAN_MODE_STANDBY 1 //CAN收发器待机模式
typedef struct
{
uint16_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint16_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that
will be transmitted. This parameter can be a value
of @ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the message that will
be transmitted. This parameter can be a value of
@ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be
transmitted. This parameter can be a value between
0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0
to 0xFF. */
} CanTxMsg;
/**
* @brief CAN Rx message structure definition
*/
typedef struct
{
uint16_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint16_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that
will be received. This parameter can be a value of
@ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the received message.
This parameter can be a value of
@ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be received.
This parameter can be a value between 0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to
0xFF. */
uint8_t FMI; /*!< Specifies the index of the filter the message stored in
the mailbox passes through. This parameter can be a
value between 0 to 0xFF */
} CanRxMsg;
/*********************************************************************
*
* Function Prototypes
*
*********************************************************************/
void ECAN_Init(void);
void CAN_SetMode(uint8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* ECAN_H */
系统进入休眠
#define WAKEUP_US_DELAY 200
唤醒后振荡器起振定时时间要大于1024TOSC,TOSC = OSC1周期
/*
*********************************************************************************************************
* 函 数 名: SysEnterSleep
* 功能说明: 系统进入休眠模式
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void SysEnterSleep(void)
{
CAN_SetMode(CAN_MODE_STANDBY);//CAN收发器进入待机模式
PIR5bits.WAKIF = 0; //清除CAN总线活动唤醒中断标志
PIE5bits.WAKIE = 1; //允许CAN总线活动唤醒中断
IPR5bits.WAKIP = 1; //CAN总线活动唤醒中断为高优先级
CANCON = 0x20;//禁止/休眠模式
while(CANSTATbits.OPMODE !=0x01);
OSCCONbits.IDLEN = 0;//配置休眠模式
Sleep();//进入休眠模式
__delay_us(WAKEUP_US_DELAY);
}