打印
[学习资料]

PIC18F,ECAN例程,支持CAN总线活动唤醒

[复制链接]
1360|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qcliu|  楼主 | 2019-8-1 11:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

程序说明:

处理器:PIC18F66K80系列

系统频率:32M (外部晶振8M,4倍频得到)

缓冲器:接收缓冲器0,接受滤波器0,发送缓冲器0


使用特权

评论回复
沙发
qcliu|  楼主 | 2019-8-1 11:48 | 只看该作者
源文件

/*********************************************************************
*
*                            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;        /* 用于接收 */

使用特权

评论回复
板凳
qcliu|  楼主 | 2019-8-1 11:49 | 只看该作者

/*********************************************************************
*
*     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总线活动唤醒中断为高优先级
}

使用特权

评论回复
地板
qcliu|  楼主 | 2019-8-1 11:50 | 只看该作者
/*
*********************************************************************************************************
*        函 数 名: CAN_SetMode
*        功能说明: 配置CAN收发器模式
*        形    参:mode 0,正常模式 1,待机模式
*        返 回 值: 无
*********************************************************************************************************
*/
void CAN_SetMode(uint8_t mode)
{
    if(mode == 0)
    {
        CAN_STB_SetLow();
    }
    else
    {
        CAN_STB_SetHigh();
    }
}

使用特权

评论回复
5
qcliu|  楼主 | 2019-8-1 11:50 | 只看该作者
/*********************************************************************
*
*     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"
    }   
}

使用特权

评论回复
6
qcliu|  楼主 | 2019-8-1 11:51 | 只看该作者
/*
*********************************************************************************************************
*        函 数 名: 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);           //等待发送 完成   
}

使用特权

评论回复
7
qcliu|  楼主 | 2019-8-1 11:51 | 只看该作者
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))
            {
            //        用户自定义       
            }
    }
}

使用特权

评论回复
8
qcliu|  楼主 | 2019-8-1 11:51 | 只看该作者
头文件
/*
* 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;

使用特权

评论回复
9
qcliu|  楼主 | 2019-8-1 11:52 | 只看该作者
/**
  * @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;

使用特权

评论回复
10
qcliu|  楼主 | 2019-8-1 11:52 | 只看该作者
/*********************************************************************
*
*                        Function Prototypes
*
*********************************************************************/
void ECAN_Init(void);
void CAN_SetMode(uint8_t mode);

#ifdef        __cplusplus
}
#endif

#endif        /* ECAN_H */

使用特权

评论回复
11
qcliu|  楼主 | 2019-8-1 11:53 | 只看该作者
系统进入休眠
#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);
}

使用特权

评论回复
12
xixi2017| | 2019-8-5 23:29 | 只看该作者
为何不以代码形式发帖呢。

使用特权

评论回复
13
xixi2017| | 2019-8-5 23:29 | 只看该作者

使用特权

评论回复
14
functions| | 2019-8-6 13:28 | 只看该作者
感谢分享!学习一下

使用特权

评论回复
15
qcliu|  楼主 | 2019-9-9 15:42 | 只看该作者
举手之劳呀 呵呵呵

使用特权

评论回复
16
CoolSilicon| | 2019-9-11 09:54 | 只看该作者
压缩一下,做成附件下载不就简单了...
这样一个一个的回, 有刷贴的嫌疑哈..

使用特权

评论回复
17
henglin| | 2019-9-16 23:08 | 只看该作者
mark

使用特权

评论回复
18
mjs0528| | 2019-10-6 18:02 | 只看该作者
感谢分享,感谢楼主!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

64

主题

3317

帖子

4

粉丝