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

来源:互联网 发布:ubuntu安装py模块 编辑:程序博客网 时间:2024/06/07 07:33

程序说明:

处理器: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#defineECAN_H#ifdef__cplusplusextern "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);}




原创粉丝点击