PIC16F877A在CAN通信中的应用程序

发布者:caoda143最新更新时间:2017-12-06 来源: eefocus关键字:PIC16F877A  CAN通信 手机看文章 扫描二维码
随时随地手机看文章

PIC16F877A在CAN通信中的应用程序


// ========CAN通信程序=======  
#include     
#include     
#include                // MCP2510寄存器定义 

// =========常数和变量定义=========   
#define    READ    0x03                // 读MCP2510指令代码  
#define    WRITE    0x02            // 写MCP2510指令代码  
#define    RESET    0xC0            // 复位MCP2510指令代码  
#define    RTS    0x80                // MCP2510请求发送指令代码  
#define    STA2510    0xA0            // 读MCP2510状态指令代码  
#define    BITMOD    0x05            // MCP2510位修改指令代码  
int    a[12];                    // SPI发送或接收数据寄存器 
int    b[8];                    // 发送或接收的数据 
int    c[8];                    // 发送或接收的数据 
int    i;                        // 临时变量 
int    count;                    // 发送接收计数器 
int    count1=0;                // for test 
int    RecID_H=0; 
int    RecID_L=0; 
int    DLC=8; 
void SPIINT(); 
void TMR1INT(); 
void CCP1INT(); 
void SPIEXCHANGE(int count); 
void WAIT_SPI(); 
void RESET2510(); 
int  RD2510(int adress,int n); 
void WR2510(int adress,int n); 
void RTS2510(int RTSn); 
int  GETS2510(); 
void BM2510(int adress,int mask,int data); 
void SETNORMAL(); 
void TXCOMPLETE(int adress); 
void TXMSG(int DLC); 
int  RXMSG(); 
void INIT2510(); 
void INIT877(); 
void INITSPI(); 
void ACK(); 
void wait(); 
// ========主程序=======  
main(void) 

    int l,detect=0; 
    SSPIE=1; 
    TMR1IE=1; 
    CCP1IE=1; 
    CCP2IE=1; 
    PEIE=1; 
    ei();                    // 开中断  
    INIT877();                // 初始化PIC16F877芯片  
    INITSPI();                // 初始化SPI接口  
    INIT2510();                // 初始化MCP2510芯片  
    flag1=0; 
    flag2=0; 
    CCP1CON=0x05; 
    CCP2CON=0x04; 
    while(1)    { 
        RXMSG(); 
        TXMSG(8); 
    } 

// ========中断服务程序=======  
// SPI中断服务子程序  
void SPIINT() 

    SSPIF=0; 
    a[i++]=SSPBUF;            // 数据暂存a[]中  
    count-=1; 
    if(count>0)  SSPBUF=a[i];// 未发送完,继续  
    else  RE2=1;                // 否则,片选信号置高电平  
    return; 

// TMR1中断服务子程序  
void TMR1INT() 

    TMR1IF=0; 
    T1CON=0; 
    if(!flag1){ 
        TMR1H=0xfe;                // 512 μs 脉冲宽度 
        TMR1L=0x00; 
        T1CON=0x01; 
        PORTD=0xff;                // 输出所有通道 
        flag1=1; 
    } 
    else    { 
        flag1=0; 
        PORTD=0; 
        T1CON=0; 
    } 
    return; 

// CCP1中断服务子程序  
void CCP1INT() 

    CCP1IF=0; 
    T1CON=0x01; 
    return; 

// CCP2中断服务子程序  
 void CCP2INT() 

    CCP2IF=0; 
    T1CON=0x01; 
    return; 

// 中断入口,保护现场,判中断类型  
void interrupt INTS() 

    di(); 
    if(TMR1IF)  TMR1INT();        // 定时器TMR1中断  
    else if(CCP1IF)  CCP1INT();    // 电压过零捕捉中断1  
    else if(CCP2IF)  CCP2INT();    // 电压过零捕捉中断2  
    else if(SSPIF)  SPIINT();        // SPI接口中断  
    ei(); 

// ========子程序=======  
// 启动SPI传送  
 void SPIEXCHANGE(count) 
 int count; 

    if(count>0) {                // 有数据可送?  
      i=0; 
      RE2=0;                        // 片选位置低电平  
      SSPBUF=a[i];                // 送数  
    } 
    else 
      ;                            // 否则,空操作,并返回  
    return; 

// 等待SPI传送完成  
 void WAIT_SPI() 

    do{ 
      ; 
    }while(count>0);                // 当count!=0时,等待 to add "CLRWDT"  
    return; 

// 对MCP2510芯片进行复位  
void RESET2510() 

    a[0]=RESET; 
    count=1; 
    SPIEXCHANGE(count);            // 送复位指令  
    WAIT_SPI(); 
    return; 

// 读取从地址"adress"开始的寄存器中的数据,共n个,存放在数组b[n]中  
 int RD2510(adress,n) 
 int     adress; 
 int        n; 

    int j; 
    a[0]=READ; 
    a[1]=adress; 
    for(j=0;j    count=n+2;                    // 指令、地址和要得到的数据量n  
    SPIEXCHANGE(count); 
    WAIT_SPI(); 
    for(j=0;j    return; 

// 向从地址"adress"开始的寄存器写入数据,共n个,数据存放数组b[n]中  
 void WR2510(adress,n) 
 int        adress; 
 int        n; 

    int j; 
    a[0]=WRITE; 
    a[1]=adress; 
    for(j=0;j    count=n+2;                    // 指令、地址和要写入的数据量n  
    SPIEXCHANGE(count); 
    WAIT_SPI(); 
    return; 

// MCP2510芯片请求发送程序  
 void RTS2510(RTSn) 
 int RTSn; 

    a[0]=RTS^RTSn; 
    count=1; 
    SPIEXCHANGE(count);            // 发送MCP2510芯片,请求发送指令  
    WAIT_SPI(); 
    return; 

// 读取MCP2510芯片的状态  
 int GETS2510() 

    a[0]=STA2510; 
    a[1]=0; 
    count=2; 
    SPIEXCHANGE(count);            // 读取MCP2510芯片状态  
    WAIT_SPI(); 
    b[0]=a[1];                    // 状态存到数组b[]中  
    return; 

// 对MCP2510芯片进行位修改子程序  
 void BM2510(adress,mask,data) 
 int  adress; 
 int  mask; 
 int  data; 

    a[0]=BITMOD;                    // 位修改指令  
    a[1]=adress;                    // 位修改寄存器地址  
    a[2]=mask;                    // 位修改屏蔽位  
    a[3]=data;                    // 位修改数据  
    count=4; 
    SPIEXCHANGE(count); 
    WAIT_SPI(); 
    return; 

// 设置MCP2510芯片为正常操作模式  
void  SETNORMAL() 

    int  k=1; 
    BM2510(CANCTRL,0xe0,0x00);    // 设置为正常操作模式  
    do    { 
      RD2510(CANSTAT,1); 
      k=b[0]&0xe0; 
    }while(k);                    // 确认已进入正常操作模式  
    return; 

// 对MCP2510进行初始化  
void INIT2510() 

    RESET2510();                    // 使芯片复位  
    b[0]=0x02; 
    b[1]=0x90; 
    b[2]=0x07; 
    WR2510(CNF3,3);                // 波特率为 125 kbps  
    b[0]=0x00; 
    b[1]=0x00; 
    WR2510(RXM0SIDH,2); 
    b[0]=0x00; 
    b[1]=0x00; 
    WR2510(RXF0SIDH,2);            // RX0接收,屏蔽位为0,过滤器为0  
    b[0]=0x00; 
    WR2510(CANINTE,1);            // CAN中断不使能  
    SETNORMAL();                    // 设置为正常操作模式  
    return; 

// MCP2510芯片发送完成与否判断,邮箱号为adress  
void TXCOMPLETE(adress) 
int adress; 

    int k=1; 
    do    { 
      RD2510(adress,1); 
      k=b[0]&0x08; 
    }while(k);                    // 确认是否已发送完毕 to add CLRWDT  
    return; 

// 初始化PIC16F877芯片  
void INIT877() 

    PORTA=0; 
    PORTB=0; 
    PORTC=0; 
    PORTD=0; 
    PORTE=0; 
    TRISA=0xff; 
    TRISB=0xfd; 
    TRISC=0xd7;                    // SCK, SDO:输出,SDI:输入   
    TRISD=0; 
    TRISE=0x03;                    // 片选CS信号输出 
    PORTA=0xff; 
    PORTB=0x03;                    // RST=1  
    PORTC=0; 
    PORTD=0xff; 
    PORTE=0x04; 
    return; 

// 初始化SPI接口  
 void INITSPI() 

    SSPCON=0x11; 
    SSPEN=1;                            // SSP使能  
    SSPSTAT=0; 
    return; 

// 发送数据子程序  
 void  TXMSG(int DLC) 

    for(i=0;i    WR2510(TXB0D0,DLC);     
    b[0]=DLC; 
    WR2510(TXB0DLC,1); 
    b[0]=0x03; 
    b[1]=RecID_H; 
    b[2]=RecID_L; 
    WR2510(TXB0CTRL,3); 
    RTS2510(0x01);                    // 请求发送  
    TXCOMPLETE(TXB0CTRL);                 //等待发送完毕  
    return; 

// 接收数据子程序  
 int RXMSG() 

    int k; 
    RD2510(CANINTF,1); 
    k=b[0]&0x01; 
    if(k==1)    {  
    BM2510(CANINTF,0x01,0x00); 
        RD2510(RXB0SIDH,2); 
        RecID_H=b[0]; 
    RecID_L=b[1]&0xe0; 
    RD2510(RXB0DLC,1); 
    DLC=b[0]&0x0f; 
    RD2510(RXB0D0,DLC); 
        for(i=0;i        return 1; 
    } 
    return 0; 


关键字:PIC16F877A  CAN通信 引用地址:PIC16F877A在CAN通信中的应用程序

上一篇:pic16f877a c语言时钟程序
下一篇:PIC测试配置位的使用

推荐阅读最新更新时间:2024-03-16 15:48

PIC16F877A驱动12864液晶
本程序配套液晶为金鹏的12864液晶使用串行模式 头文件 #ifndef LCD12864_H #define LCD12864_H #include main.h //define control port pin //serial mode //#define SCLK RD4 //#define STD RD5 //#define LCD_EN RD6 //parallel mode #define PSB RA0 #define CS RA1 #define STD RA2 #define SCLK RA3 #define RST RA4 //define command word #define CLR_LC
[单片机]
直流电机脉宽调速
测试环境:MPLAB IDE v8.73 测试芯片:PIC16F877A 所需器件: PIC16F877A单片机最小系统板 L298N电机驱动模块 4P杜邦线 最终的主要的电路实物连接图 最终测试图 电路连接图: 对应程序一的电路原理图 程序一:简单实现两个电机的正反转,未加调速。 #include pic.h //调用头文件,可以去PICC软件下去查找PIC16F87XA单片机的头文件 __CONFIG(XT&WDTDIS&LVPDIS); //定义配置字,晶振类型:XT,关闭开门狗,禁止低电压编程 /*宏定义区*/ #define IN1 RB7//Left
[单片机]
直流电机脉宽调速
STM32F429 CAN通信不成功
最近因为CAN的问题弄了我好几天时间,总结一下: 1:STM32F407开发板回环模式与CAN1给CAN2发数据都是OK的,STM32F429不行。 对比初始化函数以及检查硬件,120欧电阻还是要的,什么光耦电路能去掉还是去掉,H/L直接从TJA1050芯片出来即可。 2:STM32F407与STM32F429回环模式,can1与can2通信都成功,但是STM32F407与STM32F429通信不成功。 这是为毛啊??不急,再做个试验,STM32F429两块板子能通信成功,不存在硬件问题了,定位应该是波特率不匹配的问题。 按照STM32规格书波特率计算方式应该是: can波特率=(APB1时钟/(分频系数*
[单片机]
3.3VCC供电下实现标准的HS-CAN通信
概述 如果保证MAX13041的VCC电源处于4.75V至5.25V (标称工作电压范围),则可满足ISO 11898-2高速CAN通信标准1。也就是说,如果需要进行CAN通信,必须采用5V电源为CAN收发器供电。 然而,系统设计中常碰到的问题是主电源无法满足子系统的电源需求。这种情况下,无法直接使用现有电源:仅有一路3.3V电源或不能直接采用电池电压获得所有需要的电源。由于电路板空间有限,不能包含所有电源。有些情况下,直接从电池电源产生5V电压可能无法接受,因为存在散热问题,特别是在需要高电池电压进行CAN通信的系统中(如,汽车中两节电池供电的情况或在24V卡车系统中)。 电压转换器能够产生所需的各种电压,并且在要求低功
[嵌入式]
STM32F7xx —— CAN通信
一、CAN基础 差分信号:显性电平对应逻辑0,CAN_H和CAN_L差为2.5V;隐形电平对应逻辑1,CAN_H和CAN_L差为0V。 CAN总线的开始和结束都有一个120Ω的终端电阻。 数据帧:标准帧11位, 扩展帧29位。 其他的一些理论知识就不再赘述了,可以参考维基百科对于CAN的描述。 STM32F7xx的bxCAN主要特点:支持CAN2.0A和CAN2.0B,波特率高达1Mbps,支持时间触发,具有3个发送邮箱,2个接收邮箱,可变的过滤器组等。 二、几个重要的CAN函数 HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan); // CAN
[单片机]
PIC16F877A-UART
#include pic16f877.h #define unchar unsigned char #define uint unsigned intunchar RC_label;//标志位起始位为1结束位为0 unchar caiji_label;//采集帧格式标志位正确为1错误为0 unchar data RC ;//存储接收到的数据 unchar data TX1 ;//存储自身参数 unchar data TX2 ;//存储出错指示ERROR int RC_buff;// int i=0,j=0,k=0;// //*****串口初始化********** void initRS232() { //设置TXSTA
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved