⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 发送.c

📁 51系列单片机CAN多点通信C语言源代码
💻 C
字号:
#include <c8051f040.h>                          // SFR declarations

// CAN Protocol Register Index for CAN0ADR, from TABLE 18.1 of the C8051F040
// datasheet
////////////////////////////////////////////////////////////////////////////////
#define CANCTRL            0x00                 //Control Register
#define CANSTAT            0x01                 //Status register
#define ERRCNT             0x02                 //Error Counter Register
#define BITREG             0x03                 //Bit Timing Register
#define INTREG             0x04                 //Interrupt Low Byte Register
#define CANTSTR            0x05                 //Test register
#define BRPEXT             0x06                 //BRP Extension         Register
////////////////////////////////////////////////////////////////////////////////
//IF1 Interface Registers
////////////////////////////////////////////////////////////////////////////////
#define IF1CMDRQST         0x08                 //IF1 Command Rest      Register
#define IF1CMDMSK          0x09                 //IF1 Command Mask      Register
#define IF1MSK1            0x0A                 //IF1 Mask1             Register
#define IF1MSK2            0x0B                 //IF1 Mask2             Register
#define IF1ARB1            0x0C                 //IF1 Arbitration 1     Register
#define IF1ARB2            0x0D                 //IF1 Arbitration 2     Register
#define IF1MSGC            0x0E                 //IF1 Message Control   Register
#define IF1DATA1           0x0F                 //IF1 Data A1           Register
#define IF1DATA2           0x10                 //IF1 Data A2           Register
#define IF1DATB1           0x11                 //IF1 Data B1           Register
#define IF1DATB2           0x12                 //IF1 Data B2           Register
////////////////////////////////////////////////////////////////////////////////
//IF2 Interface Registers
////////////////////////////////////////////////////////////////////////////////
#define IF2CMDRQST         0x20                 //IF2 Command Rest      Register
#define IF2CMDMSK          0x21                 //IF2 Command Mask      Register
#define IF2MSK1            0x22                 //IF2 Mask1             Register
#define IF2MSK2            0x23                 //IF2 Mask2             Register
#define IF2ARB1            0x24                 //IF2 Arbitration 1     Register
#define IF2ARB2            0x25                 //IF2 Arbitration 2     Register
#define IF2MSGC            0x26                 //IF2 Message Control   Register
#define IF2DATA1           0x27                 //IF2 Data A1           Register
#define IF2DATA2           0x28                 //IF2 Data A2           Register
#define IF2DATB1           0x29                 //IF2 Data B1           Register
#define IF2DATB2           0x2A                 //IF2 Data B2           Register
////////////////////////////////////////////////////////////////////////////////
//Message Handler Registers
////////////////////////////////////////////////////////////////////////////////
#define TRANSREQ1          0x40                 //Transmission Rest1 Register
#define TRANSREQ2          0x41                 //Transmission Rest2 Register

#define NEWDAT1            0x48                 //New Data 1            Register
#define NEWDAT2            0x49                 //New Data 2            Register

#define INTPEND1           0x50                 //Interrupt Pending 1   Register
#define INTPEND2           0x51                 //Interrupt Pending 2   Register

#define MSGVAL1            0x58                 //Message Valid 1       Register
#define MSGVAL2            0x59                 //Message Valid 2       Register

////////////////////////////////////////////////////////////////////////////////
//Global Variables
////////////////////////////////////////////////////////////////////////////////
 #define uchar unsigned char
 uchar sdata[9]={0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x31};//发送缓冲区
char MsgNum;
char status;
int i;
int j;
int MOTwoIndex = 0;
int MOOneIndex = 0;
int StatusCopy;
int RXbuffer [4];
int TXbuffer [8];
int MsgIntNum;
int Temperature;
sbit BUTTON = P2^0;
sbit BUTTON1= P2^1;
sbit BUTTON2= P2^2;
sbit BUTTON3= P2^3;
sbit LED = P1^6;
sfr16 CAN0DAT = 0xD8;



////////////////////////////////////////////////////////////////////////////////
// Function PROTOTYPES
////////////////////////////////////////////////////////////////////////////////

// Initialize Message Object
void clear_msg_objects (void);
void init_msg_object_TX (char MsgNum,int id);
void init_msg_object_RX (char MsgNum);
void start_CAN (void);
void transmit_data(char MsgNum);
void receive_data (char MsgNum);
void external_osc (void);
void config_IO (void);
void delay(int tim);
void uart_init();
void time_init();

void delay(int tim)
{ int i,j;
  for(i=0;i<tim;i++)
  {for(j=0;j<i;j++);}
}

////////////////////////////////////////////////////////////////////////////////
// MAIN Routine
////////////////////////////////////////////////////////////////////////////////
void main (void) {
 
 
  // disable watchdog timer
  WDTCN = 0xde;
  WDTCN = 0xad;

  //configure Port I/O
    config_IO();
  	uart_init();
	time_init();

  // switch to external oscillator
    external_osc();


////////////////////////////////////////////////////////////////////////////////
// Configure CAN communications
//
// IF1 used for procedures calles by main program
// IF2 used for interrupt service procedure receive_data
//
// Message Object assignments:
//  0x02: Used to transmit commands to toggle its LED, arbitration number 1
//
////////////////////////////////////////////////////////////////////////////////

  // Clear CAN RAM
  clear_msg_objects();

  // Initialize message object to transmit data
  init_msg_object_TX (0x02,1);

  // Initialize message object to receive data
  init_msg_object_RX (0x01);

  // Enable CAN interrupts in CIP-51
  EIE2 = 0x20;

  //Function call to start CAN
  start_CAN();

  //Global enable 8051 interrupts
  EA = 1;
  // IE=0x90;
  //IP=0x00;//uart0中断优先级为低
  //EIP2=0x20;//can0中断优先级为高
  //Loop and wait for interrupts

   while(1)  //循环发送一组数组数据
   { 
      for(j=0;j<9;j++)
	  {
       transmit_data(0x02);
	   delay(500);	  
	  }
      
   }

  
}


////////////////////////////////////////////////////////////////////////////////
// Set up C8051F040
////////////////////////////////////////////////////////////////////////////////

// Switch to external oscillator
void external_osc (void)//系统晶振配置
{
  int n;                        // local variable used in delay FOR loop.
  SFRPAGE = CONFIG_PAGE;        // switch to config page to config oscillator
  OSCXCN  = 0x77;               // start external oscillator; 22.1 MHz Crystal
                                // 采用外部时钟且为2分频
                                // system clock is 22.1184MHz / 2 = 11.0592 MHz
  for (n=0;n<255;n++);          // delay about 1ms
  while ((OSCXCN & 0x80) == 0); // wait for oscillator to stabilize
  CLKSEL |= 0x01;               // switch to external oscillator
}

void config_IO (void)      // IO口配置
{
  SFRPAGE  = CONFIG_PAGE;  // Port SFR's on Configuration page
  XBR3     = 0x80;         // Configure CAN TX pin (CTX) as push-pull digital output
  P1MDOUT |= 0x40;         // Configure P1.6 as push-pull to drive LED
  XBR2     = 0x40;         // Enable Crossbar/low ports
  XBR0     = 0x04;         // bit2=1,UART0 TX0配置到P0.0,RX0配置到P0.1
  P0MDOUT  = 0X10;         // P0口输出模式控制, 1:相应口为推挽输出模式
}

////////////////////////////////////////////////////////////////////////////////
//CAN Functions
////////////////////////////////////////////////////////////////////////////////

//Clear Message Objects
void clear_msg_objects (void)//将所有的消息清 0
{
  SFRPAGE  = CAN0_PAGE;
  CAN0ADR  = IF1CMDMSK;      // Point to Command Mask Register 1
  CAN0DATL = 0xFF;           // Set direction to WRITE all IF registers to Msg Obj
  for (i=1;i<33;i++)         // i 上面定义了 i 为全局变量   
    {
      CAN0ADR = IF1CMDRQST;  // Write blank (reset) IF registers to each msg obj
      CAN0DATL = i;
    }
}

//Initialize Message Object for RX
void init_msg_object_RX (char MsgNum)//初始化接收消息体
{
  SFRPAGE  = CAN0_PAGE;
  
  CAN0ADR  = IF1CMDMSK;  // Point to Command Mask 1
  CAN0DAT  = 0x00F8;     // Set to WRITE, and alter all Msg Obj except ID MASK
                         // and data bits
  CAN0ADR  = IF1MSK1;
  CAN0DAT  = 0xFFFF;     //MSK15~0标识符
  CAN0DAT  = 0x0000;     //不进行报文滤波  

  CAN0ADR  = IF1ARB1;    // Point to arbitration1 register
  CAN0DAT  = 0xBBBB;     // Set arbitration1 ID to "0"
  CAN0DAT  = 0x8004;     // Arb2 high byte:Set MsgVal bit, no extended ID,接收标识符
                         // Dir = RECEIVE
  CAN0DAT  = 0x0480;     // Msg Cntrl: set RXIE, remote frame function disabled,单数据帧
  CAN0ADR  = IF1CMDRQST; // Point to Command Request reg.
  CAN0DATL = MsgNum;     // Select Msg Obj passed into function parameter list 消息对象与IFX之间的数据传输开始
                         // --initiates write to Msg Obj
  // 3-6 CAN clock cycles to move IF register contents to the Msg Obj in CAN RAM
}

//Initialize Message Object for TX
void init_msg_object_TX (char MsgNum,int id)//初始化发送消息体
{ int temp;
  SFRPAGE = CAN0_PAGE;  // 切换到CAN寄存器页
  CAN0ADR = IF1CMDMSK;  // Point to Command Mask 1
  CAN0DAT = 0x00B2;     // Set to WRITE, & alter all Msg Obj except ID MASK bits
                        // 设定读写方向(写),改变所有信息目标但MASK位不变

  CAN0ADR = IF1ARB1;    // Point to arbitration1 register
  CAN0DAT = 0x0000;     // Set arbitration1 ID to highest priority
                        // 即ID15-0=0
  //CAN0DAT = 0xA008;   // Autoincrement to Arb2 high byte:发送标识符设置

  //CAN0ADR = IF1ARB2   // CAN0ADR会自动加0,所以这一行要不要都可以
   temp=id<<2;
   temp&=0x1fff;
   temp|=0xa000;
   CAN0DAT=temp;        // IFx arbitration 2 register = 101 (id) 00   最后两个0是左移2位形成的
                        // MsgVal=1,该消息对象参与报文收发 Xtd=0,ID为11位,Dir=1,报文传输方向为发送

  CAN0DAT = 0x0081;     // Msg Cntrl: DLC = 1, remote frame function not enabled(远程帧功能未启用)
                        // EoB=1 当消息对象只是应用与单数据帧场合,则此位须置1,书213页
                        // 数据帧的数据长度为1个字节(DLC = 1)

  CAN0ADR = IF1CMDRQST; // Point to Command Request reg.
  CAN0DAT = MsgNum;     // Select Msg Obj passed into function parameter list
                        // --initiates write to Msg Obj
  // 3-6 CAN clock cycles to move IF reg contents to the Msg Obj in CAN RAM.
}

//Start CAN
void start_CAN (void)  //开can,初始化
{
  SFRPAGE  = CAN0_PAGE;
  CAN0CN  |= 0x41;       // 将 CCE and INIT 位置1,开始初始化
  CAN0ADR  = BITREG   ;  // Point to Bit Timing register
  CAN0DAT  = 0x2640;     // see above

  CAN0ADR  = IF1CMDMSK;  // Point to Command Mask 1
  CAN0DAT  = 0x0087;     // Config for TX : WRITE to CAN RAM, write data bytes,
                         // set TXrqst/NewDat, clr IntPnd

  // RX-IF2 operation may interrupt TX-IF1 operation
  CAN0ADR  = IF2CMDMSK;  // Point to Command Mask 2
  CAN0DATL = 0x1F;       // Config for RX : READ CAN RAM, read data bytes,
                         // clr NewDat and IntPnd
  CAN0CN  |= 0x06;       // 允许全局中断 Global Int. Enable IE and SIE
  CAN0CN  &= ~0x41;      // Clear CCE and INIT bits, starts CAN state machine
}

//Transmit CAN frame to turn other node's LED ON
void transmit_data(char MsgNum)//发送消息体发送数据
{int pass;
  SFRPAGE  = CAN0_PAGE;  // IF1 already set up for TX
  CAN0ADR  = IF1CMDMSK;  // Point to Command Mask 1
  CAN0DAT  = 0x0087;     // Config to WRITE to CAN RAM, write data bytes,
                         // set TXrqst/NewDat开始消息报文发送, Clr IntPnd
  //CAN0ADR=IF2MSGC; //消息接口寄存器2的
 // pass=CAN0DAT;

 // if(pass&0x8000 !=0)
   CAN0ADR  = IF1DATA1;   // 指向数据场的第一个字节 Point to 1st byte of Data Field
    
  CAN0DATL =sdata[j];     // j 上面定义了 j 为全局变量
  
  //CAN0DATL = 0x35;      // Ones signals to turn LED's light ON in data A1 field
  
  CAN0ADR  = IF1CMDRQST;  // Point to Command Request Reg.
  CAN0DATL = MsgNum;      // Move new data for TX to Msg Obj "MsgNum"
   
}




// Receive Data from the IF2 buffer
void receive_data(char MsgNum)//接收消息体中接收数据
{
  char receive_data;
  SFRPAGE  = CAN0_PAGE; // IF1 already set up for RX
  CAN0ADR  = IF2CMDRQST;// Point to Command Request Reg.
  CAN0DATL = MsgNum;    // Move new data for RX from Msg Obj "MsgNum"
                        // Move new data to a
  CAN0ADR  = IF2DATA1;  // Point to 1st byte of Data Field

  receive_data = CAN0DATL;
  if (receive_data == 0x11)   //Ones is signal from other node to turn LED ON
    LED = 1;
  else  LED = 0;                //Otherwise turn LED OFF (message was one's)
  SFRPAGE = UART0_PAGE; //发送完了后消息体中存储的数据改变了,通过单步调试可以发现
                        //所以每次应该先把接收到的数据取出来,另存为一个变量
  SBUF0=receive_data;
  while(TI0==0);	TI0=0;
}

////////////////////////////////////////////////////////////////////////////////
//Interrupt Service Routine
////////////////////////////////////////////////////////////////////////////////
void ISRname (void) interrupt 19 //中断子程序
{
  status = CAN0STA;
  if ((status&0x10) != 0)
    {                            
      CAN0STA = (CAN0STA&0xEF)|0x07;        
      
      receive_data (0x01);            
    }
  if ((status&0x08) != 0)
    {                           
      CAN0STA = (CAN0STA&0xF7)|0x07;        
    }
  if (((status&0x07) != 0)&&((status&0x07) != 7))
    {                           
       
      CAN0STA = CAN0STA|0x07;              
    }
}

//**************************************************************************/
void uart_init()
{
    SFRPAGE   = UART0_PAGE;
    SCON0     = 0x50;		  //允许uart0 模式1,8位UART可变波特率异步传输

}
/*************************************************************************
*
*定时器1初始化,作为UART0的波特率发生器
*************************************************************************/
void time_init()
{
    SFRPAGE   = TIMER01_PAGE;
    TCON      = 0X40;
	TMOD      = 0x20;
    CKCON     = 0X10;
	TH1       = 0xDC; //0xDC=220: 11.0592 M /(256-220) * 1/32=9600
	TR1=1;


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -