×
单片机 > 单片机程序设计 > 详情

PIC18F45K80 CAN通讯示例代码

发布时间:2024-05-19 发布时间:
|

这里转载的是别人现成的代码,进行了实际的编译和下载运行,罗列了实际运行中出现的问题,主要是证明代码的可靠性。


1、新建工程、选择好器件、选择编译环境,我当时选择的是C:Program Files (x86)Microchipmplabc18v3.47文件夹下的C18编译器。实际操作时,我当时误选了_mplink.exe,实际上选择的应该是mplink.exe文件。编译时出现错误,重新选择后,错误消除。


2、文件如下


源文件


main.c


#pragma config XINST = OFF // CONFIG1L

#pragma config FOSC = INTIO2, FCMEN = OFF, IESO = OFF ,PLLCFG = OFF // CONFIG1H

#pragma config BOREN = OFF, BORV = 0 // CONFIG2L

#pragma config WDTEN = OFF // CONFIG2H

/** I N C L U D E S **************************************************/

#include "main.h"

unsigned char CAN_RecFLAG=0;

unsigned char Flag50ms = 0;

// AD采样的数据变量

unsigned int VoltageEdlc[5];

unsigned int VoltageBat;

unsigned int Current1;

unsigned int Current2;

unsigned int Temperature1;

unsigned int Temperature2;

void InterruptHandler(void);

#pragma code high_vector=0x08

void high_interrupt (void)

{

_asm GOTO InterruptHandler _endasm

}

#pragma code

#pragma code low_vector=0x18

void low_interrupt (void)

{

_asm GOTO InterruptHandler _endasm

}

#pragma code

#pragma interruptlow InterruptHandler

#pragma interrupt InterruptHandler

void InterruptHandler(void)

{

static unsigned char Tick = 0;

static unsigned char ChannelNo = 0;

// 定时器0

if(INTCONbits.TMR0IF&&INTCONbits.TMR0IE) // timer0 = 10ms

{

INTCONbits.TMR0IF = 0;

TMR0H = 0x63;

TMR0L = 0xBF;

Tick++;

if(Tick ==200)

{

Flag50ms = 1; // 5s发送CAN消息到ECU

Tick = 0;

LATCbits.LATC5 = ~LATCbits.LATC5;

}

}

// CAN接收数据

if(PIR5bits.RXB0IF==1)

{

CAN_RecFLAG=1;

PIR5bits.RXB0IF=0; // 清接收中断标志

RXB0CONbits.RXFUL=0; // 清除标志,接收新报文

}

}

#pragma code

void main(void)

{

unsigned int EDLC_temp[4];

INTCON=0x00;

InitInterOSC();

InitPORT();

InitCan();

Timer0_Init();

// INTCON=0xc0; //使能中断 1100 0000

INTCONbits.GIE=1;

INTCONbits.PEIE=1;

// INTCONbits.GIEL=1;

// TXB0CONbits.TXREQ = 0;

while(1)

{

if(CAN_RecFLAG==1)

{

CAN_RecFLAG = 0;

TXB0D0=1; /* 写发送缓冲器数据区数据初值 */

TXB0D1=2;

TXB0D2=3;

TXB0D3=4;

TXB0D4=5;

TXB0D5=6;

TXB0D6=7;

TXB0D7=8;

TXB0CONbits.TXERR = 0;

TXB0CONbits.TXREQ=1; //请求发送,TXREQ=1

// while(TXB0CONbits.TXREQ){;}

while(!PIR5bits.TXB0IF){;}

Delay10KTCYx(1000);

Delay10KTCYx(1000);

}

}

}



SysInit.c


#include "main.h"

#include "p18f45k80.h"

void InitInterOSC(void)

{

// Set the internal oscillator to 64MHz

OSCCONbits.IRCF = 7; // 16 M

OSCTUNEbits.PLLEN = 0;

}

void InitPORT(void)

{

/*

RE2 RE1 RE0 RA5 RA3 RA2 RA1 RA0

AN7 AN6 AN5 AN4 AN3 AN2 AN1 AN0 : ANCON0

Current2 Current1 BatV C5 C4 C3 C2 C1

RB0 RB4 RB1

X X X X X AN10 AN9 AN8 : ANCON1

temp2 temp1

*/

ANCON0 = 0xff;

ANCON1 = 0x03; // 模拟/数字口选择

TRISA = 0b00101111; // RA方向寄存器

TRISB = 0b11111010; // RB方向寄存器

TRISC = 0b00000000; // RC方向寄存器

TRISD = 0b10010000; // RD方向寄存器

TRISE = 0b00001111; // RE方向寄存器

LATCbits.LATC1 = 0; // disable buck

LATCbits.LATC2 = 0; // disable boost

LATCbits.LATC4 = 1; // enable Aux power

}

// 使用16位定时器,使用内部时钟16Mhz,周期是4/16M = 0.25uS, TMR0H=TMR0L=0.定时时间2^16 = 65535/4uS=16.383mS

void Timer0_Init(void)

{

// RCONbits.IPEN=1; //打开中断高低优先级

INTCONbits.TMR0IE = 1; // 允许定时器0溢出中断

INTCONbits.TMR0IF = 0; // 清除中断标志

// INTCON2bits.TMR0IP = 0; // 设置定时器0中断为低优先级

T0CON = 0b00001000; // 定时器0设定为16位定时器,内部时钟触发,不使用分频器

// T0CON = 0b00000001; // 定时器0设定为16位定时器,内部时钟触发,使用分频器,1:4分频比

TMR0H = 0x63; // clear timer - always write upper byte first

TMR0L = 0xBF; // timer = 10ms

// INTCONbits.GIE=1;

// INTCONbits.PEIE=1;

// INTCONbits.GIEL=1;

T0CONbits.TMR0ON=1;

}

// need to set to 500kbps,standard frame

void InitCan(void)

{

TRISB=(TRISB|0x08)&0xFB; //设置CANRX/RB3为输入,CANTX/RB2为输出

CANCON = 0x80;

while(CANSTAT&0x80==0){;}

// 500Kbps@16M

BRGCON1 = 0x00; //0000 0100

BRGCON2 = 0xb8; //1011 1010

BRGCON3 = 0x05; //0000 0101

CIOCON=0X00;

ECANCON=0x00;

//设置发送邮箱0标识符号和发送的数据

TXB0CON=0x03; // TXB0发送优先级为最高优先级,TXPRI=11

TXB0SIDH=0b01010001; // 设置发送缓冲器0为标准标识符,ID = 0x28F

TXB0SIDL=0b11100000;

// TXB0SIDH=0x00; // 设置发送缓冲器0为标准标识符,ID = 0x28F

// TXB0SIDL=0x00;

TXB0DLC=0x08; // 设置数据长度为8个字节

TXB0D0=0X10; /* 写发送缓冲器数据区数据初值 */

TXB0D1=0X11;

TXB0D2=0X12;

TXB0D3=0X13;

TXB0D4=0X14;

TXB0D5=0X15;

TXB0D6=0X16;

TXB0D7=0X17;

//设置接收邮箱0的标识符和初始化数据

RXB0SIDH=0Xff; // 设置接收缓冲器0的标识符 ID = 0x26D

RXB0SIDL=0Xe0;

RXB0CON=0X20; // 仅仅接收标准标识符,FILHIT0=0表示RXB0采用filter0

RXB0DLC=0X08; // 设置接收缓冲器0的数据区长度

//初始化接收滤波器0,Id = 0x26D = 0b 010 0110 1101

RXF0SIDH=0b01001101;

RXF0SIDL=0b10100000;

//初始化接收屏蔽器0,所有11位都比较滤波

RXM0SIDH=0Xff;

RXM0SIDL=0Xe0;

//所有ID 都进来

// RXM0SIDH=0X00;

// RXM0SIDL=0X00;

Nop();

//使CAN进入某种工作模式

CANCON=0x00; //=0X40,进入自测试模式;=0x00,正常操作模式

while(CANSTAT&0XE0!=0){;}

//while(CANSTAT&0X40==0){;}

//初始化CAN的中断

PIR5=0X00; //清所有中断标志

PIE5=0X01; //使能接收缓冲器0的接收中断

// IPR5=0X01; //接收缓冲器0的接收中断为最高优先级

}



头文件


main.H


#ifndef _MAIN_H_

#define _MAIN_H_

#include

#include

#include "SysInit.h"

extern unsigned int VoltageEdlc[5];

extern unsigned int VoltageBat;

extern unsigned int Current1;

extern unsigned int Current2;

extern unsigned int Temperature1;

extern unsigned int Temperature2;

#endif



p18f45k80.h


/*-------------------------------------------------------------------------

* MPLAB-Cxx PIC18F45K80 processor header

*

* (c) Copyright 1999-2011 Microchip Technology, All rights reserved

*-------------------------------------------------------------------------*/

#ifndef __18F45K80_H

#define __18F45K80_H

extern volatile far unsigned char RXERRCNT;

extern volatile far union {

struct {

unsigned REC:8;

};

struct {

unsigned REC0:1;

unsigned REC1:1;

unsigned REC2:1;

unsigned REC3:1;

unsigned REC4:1;

unsigned REC5:1;

unsigned REC6:1;

unsigned REC7:1;

};

} RXERRCNTbits;

extern vola

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ..[22]
PIC18F45K80CAN通讯示例

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会