• <menu id="ugcm4"><strong id="ugcm4"></strong></menu>
  • 技術熱線: 4007-888-234

    PIC單片機C語言編程實例五

    更新時間: 2019-01-05
    閱讀量:1866

    第9章 PIC16F87X在CAN通信中的應用
    9.3 軟件清單
    // ========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;
    }

    刺激欲乱狂亲伦
  • <menu id="ugcm4"><strong id="ugcm4"></strong></menu>