📄 发送.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 + -