📄 mcp2510.c
字号:
#include "../ucos-ii/includes.h"
#include "../startup/44b.h"
#include "../inc/drv/EXIO.h"
#include "../inc/drv/can.h"
#include "../inc/drv/MCP2510.h"
#include "../ucos-ii/Uhal/Uhal.h"
#include "../ucos-ii/Uhal/isr.h"
/********************** MCP2510 Candata *********************************/
static CanData MCP2510_Candata[MCP2510_CanRevBuffer];
static int nCanRevpos=0; //接收缓冲区位置
static int nCanReadpos=0; //读取缓冲区位置
static OS_EVENT *CAN_Rev_Sem=NULL; //CAN接受信号量
#define NextCanDataPos(pos) do{(pos)=((pos)+1>=MCP2510_CanRevBuffer? 0: (pos)+1);}while(0)
/********************** MCP2510 Pin *********************************/
#define MCP2510_CS 0x4 //EXIO2
/********************** MCP2510 Instruction *********************************/
#define MCP2510INSTR_RESET 0xc0
#define MCP2510INSTR_READ 0x03
#define MCP2510INSTR_WRITE 0x02
#define MCP2510INSTR_RTS 0x80 //request to send
#define MCP2510INSTR_RDSTAT 0xa0 //read status
#define MCP2510INSTR_BITMDFY 0x05 //bit modify
#define MCP2510_Enable() do{CLREXIOBIT(MCP2510_CS);}while(0)
#define MCP2510_Disable() do{SETEXIOBIT(MCP2510_CS);}while(0)
void MCP2510_Reset()
{
MCP2510_Enable();
SendSIOData(MCP2510INSTR_RESET);
MCP2510_Disable();
}
void MCP2510_Write(int address, int value)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
MCP2510_Enable();
SendSIOData(MCP2510INSTR_WRITE);
SendSIOData((unsigned char)address);
SendSIOData((unsigned char)value);
MCP2510_Disable();
OS_EXIT_CRITICAL();
}
unsigned char MCP2510_Read(int address)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
unsigned char result;
OS_ENTER_CRITICAL();
MCP2510_Enable();
SendSIOData(MCP2510INSTR_READ);
SendSIOData((unsigned char)address);
SendSIOData(0);
result=ReadSIOData();
MCP2510_Disable();
OS_EXIT_CRITICAL();
return result;
}
unsigned char MCP2510_ReadStatus()
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
unsigned char result;
OS_ENTER_CRITICAL();
MCP2510_Enable();
SendSIOData(MCP2510INSTR_RDSTAT);
SendSIOData(0);
result=ReadSIOData();
MCP2510_Disable();
OS_EXIT_CRITICAL();
return result;
}
void MCP2510_WriteBits( int address, int data, int mask )
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
MCP2510_Enable();
SendSIOData(MCP2510INSTR_BITMDFY);
SendSIOData((unsigned char)address);
SendSIOData((unsigned char)mask);
SendSIOData((unsigned char)data);
MCP2510_Disable();
OS_EXIT_CRITICAL();
}
/*******************************************\
* 序列读取MCP2510数据 *
\*******************************************/
void MCP2510_SRead( int address, unsigned char* pdata, int nlength )
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
int i;
OS_ENTER_CRITICAL();
MCP2510_Enable();
SendSIOData(MCP2510INSTR_READ);
SendSIOData((unsigned char)address);
for (i=0; i<nlength; i++) {
SendSIOData(0);
*pdata=ReadSIOData();
pdata++;
}
MCP2510_Disable();
OS_EXIT_CRITICAL();
}
/*******************************************\
* 序列写入MCP2510数据 *
\*******************************************/
void MCP2510_Swrite(int address, unsigned char* pdata, int nlength)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
int i;
OS_ENTER_CRITICAL();
MCP2510_Enable();
SendSIOData(MCP2510INSTR_WRITE);
SendSIOData((unsigned char)address);
for (i=0; i < nlength; i++) {
SendSIOData((unsigned char)*pdata);
pdata++;
}
MCP2510_Disable();
OS_EXIT_CRITICAL();
}
/************************************************************\
* 设置MCP2510 CAN总线波特率 *
* 参数: bandrate为所设置的波特率 *
* IsBackNormal为是否要返回Normal模式 *
\************************************************************/
void MCP2510_SetBandRate(CanBandRate bandrate, BOOL IsBackNormal)
{
//
// Bit rate calculations.
//
//Input clock fre=16MHz
// In this case, we'll use a speed of 125 kbit/s, 250 kbit/s, 500 kbit/s.
// If we set the length of the propagation segment to 7 bit time quanta,
// and we set both the phase segments to 4 quanta each,
// one bit will be 1+7+4+4 = 16 quanta in length.
//
// setting the prescaler (BRP) to 0 => 500 kbit/s.
// setting the prescaler (BRP) to 1 => 250 kbit/s.
// setting the prescaler (BRP) to 3 => 125 kbit/s.
//
// If we set the length of the propagation segment to 3 bit time quanta,
// and we set both the phase segments to 1 quanta each,
// one bit will be 1+3+2+2 = 8 quanta in length.
// setting the prescaler (BRP) to 0 => 1 Mbit/s.
// Go into configuration mode
MCP2510_Write(MCP2510REG_CANCTRL, MODE_CONFIG);
switch(bandrate){
case BandRate_125kbps:
MCP2510_Write(CNF1, SJW1|BRP4); //Synchronization Jump Width Length =1 TQ
MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7
MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4
break;
case BandRate_250kbps:
MCP2510_Write(CNF1, SJW1|BRP2); //Synchronization Jump Width Length =1 TQ
MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7
MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4
break;
case BandRate_500kbps:
MCP2510_Write(CNF1, SJW1|BRP1); //Synchronization Jump Width Length =1 TQ
MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7
MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4
break;
case BandRate_1Mbps:
MCP2510_Write(CNF1, SJW1|BRP1); //Synchronization Jump Width Length =1 TQ
MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG3<<3)|SEG2); // Phase Seg 1 = 2, Prop Seg = 3
MCP2510_Write(CNF3, SEG2);// Phase Seg 2 = 1
break;
}
if(IsBackNormal){
//Enable clock output
MCP2510_Write(CLKCTRL, MODE_NORMAL | CLKEN | CLK1);
}
}
/*******************************************\
* 读取MCP2510 CAN总线ID *
* 参数: address为MCP2510寄存器地址*
* can_id为返回的ID值 *
* 返回值 *
* TRUE,表示是扩展ID(29位) *
* FALSE,表示非扩展ID(11位) *
\*******************************************/
BOOL MCP2510_Read_Can_ID( int address, U32* can_id)
{
U32 tbufdata;
unsigned char* p=(unsigned char*)&tbufdata;
MCP2510_SRead(address, p, 4);
*can_id = (tbufdata<<3)|((tbufdata>>13)&0x7);
*can_id &= 0x7ff;
if ( (p[MCP2510LREG_SIDL] & TXB_EXIDE_M) == TXB_EXIDE_M ) {
*can_id = (*can_id<<2) | (p[MCP2510LREG_SIDL] & 0x03);
*can_id <<= 16;
*can_id |= tbufdata>>16;
return TRUE;
}
return FALSE;
}
/***********************************************************\
* 读取MCP2510 接收的数据 *
* 参数: *
* nbuffer为第几个缓冲区可以为3或者4 *
* CanData为CAN数据结构 *
\***********************************************************/
void MCP2510_Read_Can(U8 nbuffer, PCanData candata)
{
U8 mcp_addr = (nbuffer<<4) + 0x31, ctrl;
BOOL IsExt;
char dlc;
IsExt=MCP2510_Read_Can_ID( mcp_addr, &(candata->id));
ctrl=MCP2510_Read(mcp_addr-1);
dlc=MCP2510_Read( mcp_addr+4);
if ((ctrl & 0x08)) {
candata->rxRTR = TRUE;
}
else{
candata->rxRTR = FALSE;
}
dlc &= DLC_MASK;
MCP2510_SRead(mcp_addr+5, candata->data, dlc);
candata->dlc=dlc;
}
/***********************************************************\
* 写入MCP2510 发送的数据 *
* 参数: *
* nbuffer为第几个缓冲区可以为0、1、2 *
* CanData为CAN数据结构 *
\***********************************************************/
void MCP2510_Write_Can( U8 nbuffer, PCanData candata)
{
U8 dlc;
U8 mcp_addr = (nbuffer<<4) + 0x31;
dlc=candata->dlc;
MCP2510_Swrite(mcp_addr+5, candata->data, dlc); // write data bytes
MCP2510_Write_Can_ID( mcp_addr, candata->id,candata->IsExt); // write CAN id
if (candata->rxRTR)
dlc |= RTR_MASK; // if RTR set bit in byte
MCP2510_Write((mcp_addr+4), dlc); // write the RTR and DLC
}
/*******************************************\
* 设置MCP2510 CAN总线ID *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -