日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sja1000编程c语言,基于51单片机SJA1000 CAN通讯实现(C语言程序)

發布時間:2024/3/12 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sja1000编程c语言,基于51单片机SJA1000 CAN通讯实现(C语言程序) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

經過一個星期的艱苦奮斗,終于將兩個SJA1000通過51單片機成功通訊了!采用的是Pelican工作模式,擴展幀數據格式,驗收濾波器是采用單濾波擴展幀模式。

發送和接收代碼都全部相同樣!

一 實物圖

二 串口輸出調試信息

三 以下是全部程序代碼:包括1 main.c、2 uart.h、3 uart.c、4 sja1000.h、5 sja1000.c。

1main.c

#include "reg51.h"

#include "uart.h"

#include ?"string.h"

#include ?"sja1000.h"

sbit KEY=P2^5;

void main(void)

{

unsigned char init,state,num,i=0;

UART_Init();

if(SJA_Interface_Test())

{

UART_Send_String("\r\nSJA TO CPU Right!\r\n");

}

else

{

UART_Send_String("\r\nSJA TO CPU Error!\r\n");

}

init=SJA_Init();

if(init==0)

{

UART_Send_String("\r\nSJA Init OK!\r\n");

}

else

{

UART_Send_String("\r\nSJA Init Error!\r\n");

UART_Send_Byte(init);

}

while(1)

{

if(KEY==0)

{

DelayMs(10);

if(KEY==0)

{

CAN_Send_Str("ILoveY\r\n");

Display(num);

if(num++==14) num=0;

}

DelayMs(200);

}

SJA_BCANAdr = REG_STATUS;

state=*SJA_BCANAdr;

if((state&0x40)==0x40) { UART_Send_String("\r\nSJA Error count overflow!!\r\n"); SJA_Init(); }

if((state&0x20)==0x20) ?UART_Send_String("SJA1000 CAN BUS is transmiting!\r\n");

}

}

2uart.h

#ifndef ?__UART_H__

#define ?__UART_H__

#include "stdio.h"

#include "reg51.h"

#define reclength 8

extern bit recfinish;

extern unsigned char recbuf[reclength];

void UART_Init(void);

void UART_Send_Byte(unsigned char ch);

void UART_Send_String(unsigned char *str);

void Display( char num);

void DelayMs(unsigned char t);

#endif

3uart.c

#include "uart.h"

unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

unsigned char reccount=0;

bit recstart=0;

bit recfinish=0;

unsigned char recbuf[reclength];

void UART_Init(void)

{

SCON=0X50;

TMOD|=0X20;

TH1=0XFD;

TL1=0XFD;

TR1=1;

EA=1;

ES=1;

}

void UART_Send_Byte(unsigned char ch)

{

SBUF=ch;

while(!TI);//等到發送完成中斷標志位置1

TI=0;

}

void UART_Send_String(unsigned char *str)

{

while(*str)

{

UART_Send_Byte(*str);

str++;

}

}

void UART_ISR(void) ?interrupt 4

{

//unsigned char temp;

if(RI)

{

if(recstart==0)

{

recstart=1;

reccount=0;

recfinish=0;

}

if(recstart)

{

recbuf[reccount++]=SBUF;

if((reccount==reclength)||(recbuf[reccount-1]=='z'))

{

recfinish=1;

reccount=0;

recstart=0;

}

}

}

RI=0;

}

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

uS延時函數,含有輸入參數 unsigned char t,無返回值

unsigned char 是定義無符號字符變量,其值的范圍是

0~255 這里使用晶振12M,精確延時請使用匯編,大致延時

長度如下 T=tx2+5 uS

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

void DelayUs2x(unsigned char t)

{

while(--t);

}

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

mS延時函數,含有輸入參數 unsigned char t,無返回值

unsigned char 是定義無符號字符變量,其值的范圍是

0~255 這里使用晶振12M,精確延時請使用匯編

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

void DelayMs(unsigned char t)

{

while(t--)

{

//大致延時1mS

DelayUs2x(245);

DelayUs2x(245);

}

}

//共陽數碼管顯示 調試的時候用到 ,本程序最終沒有用到。

void Display( char num)

{

P1=table[num];

}

4sja1000.h

#ifndef ?__SJA1000_H__

#define ?__SJA1000_H__

#include ?"string.h"

#include "uart.h"

#define ?SJA_BaseAdr ?0XFE00 ? ? //定義SJA RAM基址

//P2口為地址線高八位 P0口為地址線低八位

// CS接P2.0 地址線 1111 1110 0000 0000 即為0XFE00

// CS接P2.7 地址線 0111 1111 0000 0000 ? ? 0x7F00

#define ? ? ? ? REG_CONTROL ? ? ? SJA_BaseAdr+0x00 ? ? ? //內部控制寄存器

#define ? ? ? ? REG_COMMAND ? ? ? SJA_BaseAdr+0x01 ? ? ? //命令寄存器 ? ? ?只寫

#define ? ? ? ? REG_STATUS ? ? ? ?SJA_BaseAdr+0x02 ? ? ? //狀態寄存器 ? ? ?只讀

#define ? ? ? ? REG_INTERRUPT ? ? SJA_BaseAdr+0x03 ? ? ? //中斷寄存器 ? ? ?只讀

#define ? ? ? ? REG_INTENABLE ? ? SJA_BaseAdr+0x04 ? ? ? //中斷使能寄存器 ? 可讀可寫

#define ? ? ? ? REG_RESVER0 ? ? ? SJA_BaseAdr+0x05 ? ? ? //保留0

#define ? ? ? ? REG_BTR0 ? ? ? ? ?SJA_BaseAdr+0x06 ? ? ? //總線定時寄存器0 ?復位模式讀寫

//定義了波特率預設值BRP 和同步跳轉寬度SJW 的值

#define ? ? ? ? REG_BTR1 ? ? ? ? ?SJA_BaseAdr+0x07 ? ? ? //總線定時寄存器1 ?復位模式讀寫

//總線定時寄存器1 定義了每個位周期的長度采樣點的位置和在每個采樣點的采樣數目

#define ? ? ? ? REG_OCR ? ? ? ? ? SJA_BaseAdr+0x08 ? ? ? //輸出控制寄存器 ?復位模式讀寫

//輸出控制寄存器實現了由軟件控制不同輸出驅動配置的建立

#define ? ? ? ? REG_TEST ? ? ? ? ?SJA_BaseAdr+0x09 ? ? ? //測試寄存器

#define ? ? ? ? REG_RESVER1 ? ? ? SJA_BaseAdr+0x0A ? ? ? //保留1

#define ? ? ? ? REG_ARBITRATE ? ? SJA_BaseAdr+0x0B ? ? ? //仲裁丟失捕捉 ? ?只讀

#define ? ? ? ? REG_ERRCATCH ? ? ?SJA_BaseAdr+0x0C ? ? ? //錯誤代碼捕捉 ? ?只讀

#define ? ? ? ? REG_ERRLIMIT ? ? ?SJA_BaseAdr+0x0D ? ? ? //錯誤報警限額 ? ?工作模式只讀 復位模式可讀寫

#define ? ? ? ? REG_RXERR ? ? ? ? SJA_BaseAdr+0x0E ? ? ? ? //接收錯誤計數器工作模式只讀 復位模式可讀寫

#define ? ? ? ? REG_TXERR ? ? ? ? SJA_BaseAdr+0x0F ? ? ? ? //發送錯誤計數器工作模式只讀 復位模式可讀寫

#define ? ? ? ? REG_ACR0 ? ? ? ? ?SJA_BaseAdr+0x10 ? ? ? //驗收代碼寄存器

#define ? ? ? ? REG_ACR1 ? ? ? ? ?SJA_BaseAdr+0x11 ? ? ? //驗收代碼寄存器

#define ? ? ? ? REG_ACR2 ? ? ? ? ?SJA_BaseAdr+0x12 ? ? ? //驗收代碼寄存器

#define ? ? ? ? REG_ACR3 ? ? ? ? ?SJA_BaseAdr+0x13 ? ? ? //驗收代碼寄存器

#define ? ? ? ? REG_AMR0 ? ? ? ? ?SJA_BaseAdr+0x14 ? ? ? //驗收屏蔽寄存器

#define ? ? ? ? REG_AMR1 ? ? ? ? ?SJA_BaseAdr+0x15 ? ? ? //驗收屏蔽寄存器

#define ? ? ? ? REG_AMR2 ? ? ? ? ?SJA_BaseAdr+0x16 ? ? ? //驗收屏蔽寄存器

#define ? ? ? ? REG_AMR3 ? ? ? ? ?SJA_BaseAdr+0x17 ? ? ? //驗收屏蔽寄存器

// 發送緩沖區寄存器 ?(發送緩沖區長13字節,在CAN地址是16-28即0x10-0x1c)

#define ? ? ? ? REG_TXBuffer1 ? ? SJA_BaseAdr+0x10 ? ? ? ? //發送緩沖區1

#define ? ? ? ? REG_TXBuffer2 ? ? SJA_BaseAdr+0x11 ? ? ? ? //發送緩沖區2

#define ? ? ? ? REG_TXBuffer3 ? ? SJA_BaseAdr+0x12 ? ? ? ? //發送緩沖區3

#define ? ? ? ? REG_TXBuffer4 ? ? SJA_BaseAdr+0x13 ? ? ? ? //發送緩沖區4

#define ? ? ? ? REG_TXBuffer5 ? ? SJA_BaseAdr+0x14 ? ? ? ? //發送緩沖區5

#define ? ? ? ? REG_TXBuffer6 ? ? SJA_BaseAdr+0x15 ? ? ? ? //發送緩沖區6

#define ? ? ? ? REG_TXBuffer7 ? ? SJA_BaseAdr+0x16 ? ? ? ? //發送緩沖區7

#define ? ? ? ? REG_TXBuffer8 ? ? SJA_BaseAdr+0x17 ? ? ? ? //發送緩沖區8

#define ? ? ? ? REG_TXBuffer9 ? ? SJA_BaseAdr+0x18 ? ? ? ? //發送緩沖區9

#define ? ? ? ? REG_TXBuffer10 ? ?SJA_BaseAdr+0x19 ? ? ? ? //發送緩沖區10

#define ? ? ? ? REG_TXBuffer11 ? ?SJA_BaseAdr+0x1A ? ? ? ? //發送緩沖區11

#define ? ? ? ? REG_TXBuffer12 ? ?SJA_BaseAdr+0x1B ? ? ? ? //發送緩沖區12

#define ? ? ? ? REG_TXBuffer13 ? ?SJA_BaseAdr+0x1C ? ? ? ? //發送緩沖區13

// 接收緩沖區寄存器 ? (接收緩沖區長13字節,在CAN地址是16-28即0x10-0x1c)

#define ? ? ? ? REG_RXBuffer1 ? ? SJA_BaseAdr+0x10 ? ? ? //接收緩沖區1

#define ? ? ? ? REG_RXBuffer2 ? ? SJA_BaseAdr+0x11 ? ? ? //接收緩沖區2

#define ? ? ? ? REG_RXBuffer3 ? ? SJA_BaseAdr+0x12 ? ? ? ?//接收緩沖區3

#define ? ? ? ? REG_RXBuffer4 ? ? SJA_BaseAdr+0x13 ? ? ? //接收緩沖區4

#define ? ? ? ? REG_RXBuffer5 ? ? SJA_BaseAdr+0x14 ? ? ? ?//接收緩沖區5

#define ? ? ? ? REG_RXBuffer6 ? ? SJA_BaseAdr+0x15 ? ? ? ? //接收緩沖區6

#define ? ? ? ? REG_RXBuffer7 ? ? SJA_BaseAdr+0x16 ? ? ? ? //接收緩沖區7

#define ? ? ? ? REG_RXBuffer8 ? ? SJA_BaseAdr+0x17 ? ? ? ? //接收緩沖區8

#define ? ? ? ? REG_RXBuffer9 ? ? SJA_BaseAdr+0x18 ? ? ? ? //接收緩沖區9

#define ? ? ? ? REG_RXBuffer10 ? ?SJA_BaseAdr+0x19 ? ? ? ?//接收緩沖區10

#define ? ? ? ? REG_RXBuffer11 ? ?SJA_BaseAdr+0x1A ? ? ? ?//接收緩沖區11

#define ? ? ? ? REG_RXBuffer12 ? ?SJA_BaseAdr+0x1B ? ? ? ?//接收緩沖區12

#define ? ? ? ? REG_RXBuffer13 ? ?SJA_BaseAdr+0x1C ? ? ? ?//接收緩沖區13

#define ? ? ? ? REG_RXCOUNT ? ? ? SJA_BaseAdr+0x1D ? ? ? ? //RX報文計數器 ?只讀 RX信息計數器(RMC)反應RXFIFO中可用的信息數目

#define ? ? ? ? REG_RBSA ? ? ? ? ?SJA_BaseAdr+0x1E ? ? ? ? //RX緩沖器起始地址寄存器(RBSA)可讀寫 復位模式只寫

//反映了當前可用來存儲位于接收緩沖器窗口中的信息的內部RAM地址

#define ? ? ? ? REG_CDR ? ? ? ? ? SJA_BaseAdr+0x1F ? ? ? ? //時鐘分頻寄存器

//時鐘分頻寄存器為微控制器控制CLKOUT 的頻率以及屏蔽CLKOUT 引腳而且它還控制著TX1上

//的專用接收中斷脈沖接收比較通道和BasicCAN 模式與PeliCAN 模式的選擇

/*

功能說明: ? CAN控制器SJA1000通訊波特率.SJA1000的晶振為必須為16MHZ*/

#define ? ? ? ? BTR0_Rate_20k ? ? ?0x53 ? ? ? ? ?//20KBPS的預設值

#define ? ? ? ? BTR1_Rate_20k ? ? ?0x2F ? ? ? ? ?//20KBPS的預設值

#define ? ? ? ? BTR0_Rate_40k ? ? ?0x87 ? ? ? ? ?//40KBPS的預設值

#define ? ? ? ? BTR1_Rate_40k ? ? ?0xFF ? ? ? ? ?//40KBPS的預設值

#define ? ? ? ? BTR0_Rate_50k ? ? ?0x47 ? ? ? ? ?//50KBPS的預設值

#define ? ? ? ? BTR1_Rate_50k ? ? ?0x2F ? ? ? ? ?//50KBPS的預設值

#define ? ? ? ? BTR0_Rate_80k ? ? ?0x83 ? ? ? ? ?//80KBPS的預設值

#define ? ? ? ? BTR1_Rate_80k ? ? ?0xFF ? ? ? ? ?//80KBPS的預設值

#define ? ? ? ? BTR0_Rate_100k ? ? 0x43 ? ? ? ? ?//100KBPS的預設值

#define ? ? ? ? BTR1_Rate_100k ? ? 0x2f ? ? ? ? ?//100KBPS的預設值

#define ? ? ? ? BTR0_Rate_125k ? ? 0x03 ? ? ? ? ?//125KBPS的預設值

#define ? ? ? ? BTR1_Rate_125k ? ? 0x1c ? ? ? ? ?//125KBPS的預設值

#define ? ? ? ? BTR0_Rate_200k ? ? 0x81 ? ? ? ? ?//200KBPS的預設值

#define ? ? ? ? BTR1_Rate_200k ? ? 0xFA ? ? ? ? ?//200KBPS的預設值

#define ? ? ? ? BTR0_Rate_250k ? ? 0x01 ? ? ? ? ?//250KBPS的預設值

#define ? ? ? ? BTR1_Rate_250k ? ? 0x1c ? ? ? ? ?//250KBPS的預設值

#define ? ? ? ? BTR0_Rate_400k ? ? 0x43 ? ? ? ? ?//400KBPS的預設值

#define ? ? ? ? BTR1_Rate_400k ? ? 0x11 ? ? ? ? ?//400KBPS的預設值

#define ? ? ? ? BTR0_Rate_500k ? ? 0x81 ? ? ? ? ?//500KBPS的預設值

#define ? ? ? ? BTR1_Rate_500k ? ? 0x23 ? ? ? ? ?//500KBPS的預設值

#define ? ? ? ? BTR0_Rate_666k ? ? 0x41 ? ? ? ? ?//666KBPS的預設值

#define ? ? ? ? BTR1_Rate_666k ? ? 0x12 ? ? ? ? ?//666KBPS的預設值

#define ? ? ? ? BTR0_Rate_800k ? ? 0x41 ? ? ? ? ?//800KBPS的預設值

#define ? ? ? ? BTR1_Rate_800k ? ? 0x11 ? ? ? ? ?//800KBPS的預設值

#define ? ? ? ? BTR0_Rate_1000k ? ?0x40 ? ? ? ? ?//1000KBPS的預設值

#define ? ? ? ? BTR1_Rate_1000k ? ?0x23 ? ? ? ? ?//1000KBPS的預設值

//BPS

//功能說明: ? CAN控制器SJA1000通訊波特率.SJA1000的晶振為必須為24MHZ*/

#define ? ? ? ? BTR0_Rate_10k ? ? ?0xEF ? ? ? ? ?//20KBPS的預設值

#define ? ? ? ? BTR1_Rate_10k ? ? ?0xFF ? ? ? ? ?//20KBPS的預設值

#define ? ? ? ? ByteRate_10k ? ? ? 10

#define ? ? ? ? ByteRate_20k ? ? ? 20

#define ? ? ? ? ByteRate_40k ? ? ? 40

#define ? ? ? ? ByteRate_50k ? ? ? 50

#define ? ? ? ? ByteRate_80k ? ? ? 80

#define ? ? ? ? ByteRate_100k ? ? ?100

#define ? ? ? ? ByteRate_125k ? ? ?125

#define ? ? ? ? ByteRate_200k ? ? ?200

#define ? ? ? ? ByteRate_250k ? ? ?250

#define ? ? ? ? ByteRate_400k ? ? ?400

#define ? ? ? ? ByteRate_500k ? ? ?500

#define ? ? ? ? ByteRate_800k ? ? ?800

#define ? ? ? ? ByteRate_1000k ? ? 1000

//命令字

#define ? ?TR_CMD ? ? 0X01 ?//CMR.0發送請求位

#define ? ?AT_CMD ? ? 0X02 ?//CMR.1中止發送位

#define ? ?RRB_CMD ? ?0X04 ?//CMR.2釋放接收緩沖器

#define ? ?COS_CMD ? ?0X08 ?//CMR.3清除數據溢出

#define ? ?SRR_CMD ? ?0X10 ?//CMR.4自接收模式

#define ? ?GTS_CMD ? ?0X10 ?//????CMR.5.CMR7保留位

//錯誤字

#define CAN_INTERFACE_OK ? ? ?0 ? ? //CAN總線接口OK

#define CAN_BUS_OK ? ? ? ? ? ?0 ? ? //CAN總線OK

#define CAN_INTERFACE_ERR ? ? 0XFF ?//CAN總線接口錯誤

#define CAN_ENTERSET_ERR ? ? ?0XFE ?//CAN總線初始化錯誤

#define CAN_QUITSET_ERR ? ? ? 0XFD ?//CAN總線退出復位模式錯誤

#define CAN_INITOBJECT_ERR ? ?0XFC ?//CAN總線初始化對象錯誤

#define CAN_INITBTR_ERR ? ? ? 0XFB ?//?

#define CAN_INITOUTCTL_ERR ? ?0XFA ?//??

#define CAN_INTCLKDIV_ERR ? ? 0XF9 ?//??

#define CAN_BUS_ERR ? ? ? ? ? 0XF8 ?//CAN總線錯誤

#define ID28_21 ? ?0X0A;

#define ID20_13 ? ?0X4A;

#define ID12_5 ? ? 0X6B;

#define ID4_0 ? ? ?0XE8; //低三位不影響設為0

//定義擴展模式數據幀ID

//Basic CAN模式標準幀格式 :幀信息,TX識別碼1-2,TX數據字節1-8

//Pelican模式擴展幀格式 ? :幀信息,TX識別碼1-4,TX數據字節1-8

extern unsigned char xdata *SJA_BCANAdr;

bit SJA_Interface_Test(void);

bit Set_OutClock(unsigned char outclock);//只能用于復位模式

bit SET_ACR(unsigned char BCAN_ACR0,unsigned char BCAN_ACR1,unsigned char BCAN_ACR2,unsigned char BCAN_ACR3);

bit SET_AMR(unsigned char BCAN_AMR0,unsigned char BCAN_AMR1,unsigned char BCAN_AMR2,unsigned char BCAN_AMR3);

bit Set_Bandrate(unsigned char bandrate);//只能用于復位模式

bit Set_ContrREG(unsigned char CMD);//設置控制(模式)寄存器

bit Enter_RST_Mode(void);

bit Quit_RST_Mode(void);

bit CAN_CMD_PRG(unsigned char cmd);//命令請求

bit Set_IntEnable(unsigned char CMD);

unsigned char CAN_Write(unsigned char *SendDataBuf);

void CAN_Send_onebyte(unsigned char CAN_TX_data);

unsigned char SJA_Init(void);

void CAN_Send_Str(unsigned char *str);

#endif

5.sja1000.c

#include "sja1000.h"

sbit LED=P1^0;

unsigned char xdata *SJA_BCANAdr;

unsigned char RevceData[8];

//C語言指針說明以 * 為分隔符,

//“*” 前面的存儲類型修飾—指針所指向的對象數據的存儲位置;

//“*” 后面的存儲類型修飾—指針本身所分配的存儲位置。

//

//unsigned char xdata *P說明指針指向的對象是一個處于Xdata的元素,比如數組.

//xdata unsigned char *p表明指針本身位于Xdata,至于指向什么類型的地址,自由變換.

//所以unsigned char xdata *p; 和xdata unsigned char *p ? 不一樣。說明的是2回事。

//而:xdata unsigned char *p; 和 unsigned char ?* xdata p; 完全一樣。

//因為C寫法中允許“最前面的存儲類型修飾符修飾最后面的對象。”

/*****************************************************************

函數功能:檢測SJA1000與CPU數據接口是否正確連接

入口參數:

返回參數:1正確 0錯誤

說明:

******************************************************************/

bit SJA_Interface_Test(void)

{

SJA_BCANAdr=REG_TEST;

*SJA_BCANAdr=0xAA;

if(*SJA_BCANAdr==0XAA)

return 1;

else return 0;

}

/*****************************************************************

函數功能:設置分頻系數 ?工作模式

入口參數:

返回參數:1設置成功 0失敗

說明:此處設置為PeliCAN模式,終止CAN輸入比較器(復位模式),關閉時鐘輸出

******************************************************************/

bit Set_OutClock(unsigned char outclock)

{

SJA_BCANAdr=REG_CDR ;

*SJA_BCANAdr=outclock;

if(*SJA_BCANAdr==outclock)

return 1;

else return 0;

}

/*****************************************************************

函數功能:設置驗收驗收代碼寄存器和接收屏蔽碼寄存器 只有在復位模式下才能訪問該寄存器

入口參數:各個寄存器的寫入值

返回參數:1設置成功 0 設置失敗

說明:設置CAN節點的通訊對象,允許接收的報文,是由AMR和ACR共同決定的.

PeliCAN工作模式下濾波模式分為:

1.單濾波器模式 模式寄存器(MOD.3=1)

這種濾波模式可以定義一個4字節長慮波器 。慮波器字節和信息字節之位的對應關系取決于當前接收幀的格式。

標準幀:11位標識符、RTR位、數據場前連個字節參與濾波。對于參與濾波的數據,所有AMR為0的位所對應的ACR位

和參與濾波數據的對應位必須相同才算驗收通過。如果由于置位RTR位而沒有數據字節,或因為設置相應的數據長度代碼

而沒有或只有一個數據字節,報文也會被接收。ACR1和AMR1的低四位是不用的,此時可將AMR1.3-AMR1.0設為1,定為不影響

擴展幀:29位標識符和RTR位參與濾波。此時ACR3和AMR3的最低兩位是不用的。將AMR3.1、AMR3.0置1,定為不影響。

2.雙濾波器模式 模式寄存器(MOD.3=0)至少有一個濾波器驗收通過,數據才能正常接收。

接收標準幀:第一個濾波器由ACR0、ACR1、AMR0、AMR1及ACR3、AMR3的低四位組成。11位標識符、RTR位和數據場的第一個字節參與濾波

在RTR位置位1或數據長度代碼是0,表示沒有數據字節存在時,只要從開始到RTR位的部分都表示接收。信息就可以通過濾波器1

第二個濾波器由ACR2、AMR2及ACR3、AMR3的高四位組成。11位標識符和RTR位參與濾波。

如果沒有數據字節向濾波器請求過濾,AMR1和AMR3的低四位必須被置1,表示不影響。此時兩個濾波器的識別工作都是驗證

包括RTR在內的整個標準識別碼。

接收擴展幀:定義的兩個濾波器是相同的

第一個濾波器由ACR0、ACR1和AMR0、AMR1構成

第二個濾波器由ACR2、ACR3和AMR2、AMR3構成

兩個濾波器都只比較擴展識別碼的前兩個字節即29位識別碼中的搞16位

******************************************************************/

bit SET_ACR(unsigned char BCAN_ACR0,unsigned char BCAN_ACR1,unsigned char BCAN_ACR2,unsigned char BCAN_ACR3)

{

SJA_BCANAdr=REG_ACR0;

*SJA_BCANAdr=BCAN_ACR0;

SJA_BCANAdr=REG_ACR1;

*SJA_BCANAdr=BCAN_ACR1;

SJA_BCANAdr=REG_ACR2;

*SJA_BCANAdr=BCAN_ACR2;

SJA_BCANAdr=REG_ACR3;

*SJA_BCANAdr=BCAN_ACR3;

if(*SJA_BCANAdr!=BCAN_ACR3) ?return 0;

return 1;

}

bit SET_AMR(unsigned char BCAN_AMR0,unsigned char BCAN_AMR1,unsigned char BCAN_AMR2,unsigned char BCAN_AMR3)

{

SJA_BCANAdr=REG_AMR0;

*SJA_BCANAdr=BCAN_AMR0;

SJA_BCANAdr=REG_AMR1;

*SJA_BCANAdr=BCAN_AMR1;

SJA_BCANAdr=REG_AMR2;

*SJA_BCANAdr=BCAN_AMR2;

SJA_BCANAdr=REG_AMR3;

*SJA_BCANAdr=BCAN_AMR3;

if(*SJA_BCANAdr!=BCAN_AMR3) return 0;

return 1;

}

/*****************************************************************

函數功能:設置CAN總線通信波特率

入口參數:波特率

返回參數:1設置成功 0設置失敗

說明:該子程序只能用于復位模式

因為總線定時器BTRO-BTR1只有在復位模式下才能讀寫操作,工作模式只讀

******************************************************************/

bit Set_Bandrate(unsigned char bandrate)

{

unsigned char BR_Num= bandrate,BTR0_num,BTR1_num;

switch (BR_Num)

{

case ByteRate_10k:

BTR0_num=BTR0_Rate_10k;

BTR1_num=BTR0_Rate_10k;

break;

case ByteRate_20k:

BTR0_num=BTR0_Rate_20k;

BTR1_num=BTR0_Rate_20k;

break;

case ByteRate_40k:

BTR0_num=BTR0_Rate_20k;

BTR1_num=BTR0_Rate_20k;

break;

case ByteRate_50k:

BTR0_num=BTR0_Rate_50k;

BTR1_num=BTR0_Rate_50k;

break;

case ByteRate_80k:

BTR0_num=BTR0_Rate_80k;

BTR1_num=BTR0_Rate_80k;

break;

case ByteRate_100k:

BTR0_num=BTR0_Rate_100k;

BTR1_num=BTR0_Rate_100k;

break;

case ByteRate_125k:

BTR0_num=BTR0_Rate_125k;

BTR1_num=BTR0_Rate_125k;

break;

case ByteRate_200k:

BTR0_num=BTR0_Rate_200k;

BTR1_num=BTR0_Rate_200k;

break;

case ByteRate_250k:

BTR0_num=BTR0_Rate_250k;

BTR1_num=BTR0_Rate_250k;

break;

case ByteRate_400k:

BTR0_num=BTR0_Rate_400k;

BTR1_num=BTR0_Rate_400k;

break;

case ByteRate_500k:

BTR0_num=BTR0_Rate_500k;

BTR1_num=BTR0_Rate_500k;

break;

case ByteRate_1000k:

BTR0_num=BTR0_Rate_1000k;

BTR1_num=BTR0_Rate_1000k;

break;

default :return 0;break;

}

SJA_BCANAdr=REG_BTR0;

*SJA_BCANAdr=BTR0_num;

if(*SJA_BCANAdr!=BTR0_num) return 0;

SJA_BCANAdr=REG_BTR1;

*SJA_BCANAdr=BTR1_num;

if(*SJA_BCANAdr!=BTR1_num) return 0;

return 1;

}

/*****************************************************************

函數功能:設置控制(模式)寄存器

入口參數:寫入的命令

返回參數:

說明:模式寄存器的內容是用來改變CAN 控制器的行為

******************************************************************/

bit Set_ContrREG(unsigned char CMD)

{

SJA_BCANAdr ?= REG_CONTROL;//控制寄存器

*SJA_BCANAdr=CMD;

if(*SJA_BCANAdr==CMD) return 1;

else return 0;

}

/*****************************************************************

函數功能:設置復位請求和單濾波工作模式

入口參數:

返回參數:

說明:

******************************************************************/

bit Enter_RST_Mode(void)

{

SJA_BCANAdr ?= REG_CONTROL;//控制寄存器

*SJA_BCANAdr=0x09; ? ? ? ? ? //置位復位請求 和單濾波模式

if((*SJA_BCANAdr&0x01) == 1)

return ? 1;

else

return ? 0;

}/*****************************************************************

函數功能:

入口參數:

返回參數:

說明:

******************************************************************/

bit Quit_RST_Mode(void)

{

SJA_BCANAdr=REG_CONTROL; ? ? ? ? ? ?//退出 復位模式

*SJA_BCANAdr=*SJA_BCANAdr&0xfe;

if((*SJA_BCANAdr&0X01)==0)

return 1;

else return 0;

}

/*****************************************************************

函數功能:發送命令請求,并返回請求結果

入口參數:

返回參數:0請求成功 1請求失敗

說明:

******************************************************************/

bit ?CAN_CMD_PRG(unsigned char cmd)

{

SJA_BCANAdr=REG_COMMAND; ? ? ? ? ? ?//訪問地址指向命令寄存器

*SJA_BCANAdr=cmd; ? ? ? ? ? ? ? ? ? //啟動命令字

switch(cmd)

{

case ?TR_CMD: ? ?//發送請求

return ? ?1;

break;

case ?SRR_CMD: ? ? //CMR.4自接收模式

return 1;

break;

case ?AT_CMD: ? ? ?//CMR.1中止發送位

SJA_BCANAdr = REG_STATUS; ? //訪問地址指向狀態寄存器

if((*SJA_BCANAdr & 0x20)==0) //判斷是否正在發送 (0正在發送 1等待空閑)

return ?1;

else

return ?0;

break;

case ?RRB_CMD: ? // CMR.2釋放接收緩沖器

SJA_BCANAdr = REG_STATUS; ? //訪問地址指向狀態寄存器

if((*SJA_BCANAdr & 0x01)==1) //判斷接收緩沖器是否為空 (0為空 1不為空)

return ?0;//若不為空 則釋放接收緩沖器失敗

else

return ?1;

break;

case ?COS_CMD: ?//CMR.3清除數據溢出

SJA_BCANAdr = REG_STATUS;

if((*SJA_BCANAdr & 0x02)==0)//判斷清除溢出是否成功

return ?1;

else

return ?0;

break;

default:

return ?0;

break;

}

}

/*****************************************************************

函數功能:設置中斷使能寄存器

入口參數:

返回參數:

說明:

******************************************************************/

bit Set_IntEnable(unsigned char CMD)

{

SJA_BCANAdr=REG_INTENABLE; ? //SJA_BaseAdr+0x00 ?控制寄存器

*SJA_BCANAdr=CMD;

if (*SJA_BCANAdr == CMD)

return 1;

else

return 0;

}

unsigned char CAN_Write(unsigned char *SendDataBuf)

{

unsigned char temp;

SJA_BCANAdr = REG_STATUS;

temp=*SJA_BCANAdr;

if ((temp&0x08)==0) return ?1; ? ?//上次發送未完成

if ((temp&0x04)==0) return ?2; ? ?//發送緩沖區是否鎖定

if ((temp&0x10)==0x10) return 3; ?//判斷是否正在接收

SJA_BCANAdr = REG_RXBuffer1; ? ? ?//訪問地址指向發送緩沖區1,修改成頭文件

memcpy(SJA_BCANAdr,SendDataBuf,4); //將SendDataBuf起始地址的的4個字節數據拷貝到 SJA_BCANAdr 發送緩沖區中

CAN_CMD_PRG(TR_CMD); ? ? ? ? ? ? //請求發送

return 0;

}

//CAN發送一個字節

void CAN_Send_onebyte(unsigned char CAN_TX_data)

{

unsigned char temptt;

loop:

SJA_BCANAdr = REG_STATUS;

temptt=*SJA_BCANAdr;

//temptt=Read_SJA1000(REG_STATUS);

if((temptt&0x04)==0x00) ?goto loop;//循環檢測等待

//可以向發送緩沖器寫數據

SJA_BCANAdr = REG_RXBuffer1;

*SJA_BCANAdr=0x01;

SJA_BCANAdr = REG_RXBuffer2;

*SJA_BCANAdr=0x28;

SJA_BCANAdr = REG_RXBuffer3;

*SJA_BCANAdr=0x00;

SJA_BCANAdr = REG_RXBuffer4;

*SJA_BCANAdr=CAN_TX_data;

//數據發送請求

CAN_CMD_PRG(TR_CMD);

}

void CAN_Send_Str(unsigned char *str)

{

unsigned char temptt,length;

loop:

SJA_BCANAdr = REG_STATUS;

temptt=*SJA_BCANAdr;

//temptt=Read_SJA1000(REG_STATUS);

if((temptt&0x04)==0x00) ?goto loop;//循環檢測等待

//可以向發送緩沖器寫數據

length=strlen(str);

SJA_BCANAdr = REG_TXBuffer1;

*SJA_BCANAdr=0x80|length; //設置發送信息幀位擴展數據幀 和發送的數據字節長度

SJA_BCANAdr = REG_TXBuffer2;

*SJA_BCANAdr=ID28_21;

SJA_BCANAdr = REG_TXBuffer3;

*SJA_BCANAdr=ID20_13;

SJA_BCANAdr = REG_TXBuffer4;

*SJA_BCANAdr=ID12_5;

SJA_BCANAdr =REG_TXBuffer5;

*SJA_BCANAdr=ID4_0;

SJA_BCANAdr = REG_TXBuffer6;

memcpy(SJA_BCANAdr,str,length);

//數據發送請求

CAN_CMD_PRG(TR_CMD);

}

/*****************************************************************

函數功能:SJA1000初始化

入口參數:

返回參數:

說明:

******************************************************************/

unsigned char SJA_Init(void)

{

bit s;

EA=0;//關總中斷

if (!Enter_RST_Mode()) return 1; //設置模式(控制)寄存器 置位復位請求位 和驗收濾波模式位(單濾波模式)

if (!SJA_Interface_Test()) return 2; //!!!!!我覺得此處邏輯上應先測試SJA1000再進行復位操作

//0XC8=1100 0000 最高位CDR.7(CANmode位)=1=Pelican模式(=0=BasicCAN模式)

//置位CDR.6 可以中止CAN 輸入比較器 CDR.3置位關閉external CLKOUT CD2-CD0 設置時鐘分頻

//設置為PeliCAN模式,終止CAN輸入比較器(復位模式),關閉時鐘輸出

if (!Set_OutClock(0XC8)) return 3;

//設置濾波器濾波條件

SET_ACR(0x0A,0x4A,0x6B,0x78);

s=SET_AMR(0x00,0x00,0x00,0x03);

if (s==0) return 4;

if (!Set_Bandrate(ByteRate_1000k)) return 5;//設置通信波特率

if (!Set_IntEnable(0x1D)) return 6;

SJA_BCANAdr=REG_OCR ; ? ? ? ? ? ? ? //輸出控制寄存器

*SJA_BCANAdr=0x1a; ? ? ? ? ? ? ? ? ?//設置為正常輸出模式

if(!Quit_RST_Mode()) return 7;

EA=1;

PX0=1;//外部中斷0定義為高優先級中斷

EX0=1;//開啟外部中斷

IT0=0;//外部中斷0觸發方式選擇位 此處設置為低電平觸發

return 0;

}

void Int0_ISR() interrupt 0

{

unsigned char tt,length;

SJA_BCANAdr=REG_INTERRUPT;//中斷寄存器

if((*SJA_BCANAdr)&0x01) ? //產生了接收中斷

{

UART_Send_String("SJA1000 Has recieved data!\r\n");

SJA_BCANAdr=REG_RXBuffer1;//CAN地址16 ?TX幀信息 低四位DLC.3-DLC.0數據長度代碼為

tt=*SJA_BCANAdr;

length=tt&0x0F;//獲取數據長度代碼

if ((tt&0x40)!=0x40) ? ? ? ? ? ? ? ? //最高位為幀格式位=0數據幀 ? =1 為遠程幀

{

SJA_BCANAdr=REG_RXBuffer6; ? ? ? ? ? //宏定義的變量不能memcpy(RevceData,REG_RXBuffer4,8);

memcpy(RevceData,SJA_BCANAdr,length);//功能:由src所指內存區域復制count個字節到dest所指內存區域

//測試用的主要是把接收到的數據在發出去,驗證數據的正確

//以下代碼是發送到串

UART_Send_String(RevceData);

}

CAN_CMD_PRG(RRB_CMD); ? ? ? ? ? ? ? ?//釋放SJA1000接收緩沖區,****已經修改

}

}

總結

以上是生活随笔為你收集整理的sja1000编程c语言,基于51单片机SJA1000 CAN通讯实现(C语言程序)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。