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语言程序)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 心情日志 —— 2015/09/09
- 下一篇: 仿果壳网手机登陆界面源代码