用过51单片机驱动Nrf24L01无线传输数据.你能发我一份C程序吗? 有接收、发送的,有详细的吗?
展开全部
//仅供参考
#include <reg52.h> #include <intrins.h> typedef unsigned char uchar; typedef unsigned char uint; //****************************************IO 端 口 定 义 *************************************** sbit MISO =P1^2; sbit MOSI =P3^2; sbit SCK =P1^6; sbit CE =P1^5; sbit CSN =P1^7; sbit IRQ =P1^3; //*********************************** 数 码 管 0-9 编 码 ******************************************* uchar seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9 段码 uchar TxBuf[32]= { 0x01,0x02,0x03,0x4,0x05,0x06,0x07,0x08, 0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16, 0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24, 0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32, }; // //************************************ 按 键 ********************************************** sbit KEY1=P3^6; sbit KEY2=P3^7; //*********************************** 数 码 管 位 选 ************************************************** sbit led1=P2^1; sbit led0=P2^0; sbit led2=P2^2; sbit led3=P2^3; //*********************************************NRF24L01*********************** ************** #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5 // 5 uints RX address width #define TX_PLOAD_WIDTH 32 // 20 uints TX payload #define RX_PLOAD_WIDTH 32 // 20 uints TX payload uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址 //***************************************NRF24L01 寄 存 器 指 令 ******************************************************* #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送 FIFO 指令 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO 指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留 //*************************************SPI(nRF24L01) 寄 存 器 地 址 **************************************************** #define CONFIG 0x00 // 配置收发状态,CRC 校验模式以及收发状态响应方式 #define EN_AA 0x01 // 自动应答功能设置 #define EN_RXADDR 0x02 // 可用信道设置 #define SETUP_AW 0x03 // 收发地址宽度设置 #define SETUP_RETR 0x04 // 自动重发功能设置 #define RF_CH 0x05 // 工作频率设置 #define RF_SETUP 0x06 // 发射速率、功耗功能设置 #define STATUS 0x07 // 状态寄存器 #define OBSERVE_TX 0x08 // 发送监测功能 #define CD 0x09 // 地址检测 #define RX_ADDR_P0 0x0A // 频道 0 接收数据地址 #define RX_ADDR_P1 0x0B // 频道 1 接收数据地址 #define RX_ADDR_P2 0x0C // 频道 2 接收数据地址 #define RX_ADDR_P3 0x0D // 频道 3 接收数据地址 #define RX_ADDR_P4 0x0E // 频道 4 接收数据地址 #define RX_ADDR_P5 0x0F // 频道 5 接收数据地址 #define TX_ADDR 0x10 // 发送地址寄存器 #define RX_PW_P0 0x11 // 接收频道 0 接收数据长度 #define RX_PW_P1 0x12 // 接收频道 0 接收数据长度 #define RX_PW_P2 0x13 // 接收频道 0 接收数据长度 #define RX_PW_P3 0x14 // 接收频道 0 接收数据长度 #define RX_PW_P4 0x15 // 接收频道 0 接收数据长度 #define RX_PW_P5 0x16 // 接收频道 0 接收数据长度 #define FIFO_STATUS 0x17 // FIFO 栈入栈出状态寄存器设置 //***************************************************************************** ********* void Delay(unsigned int s); void inerDelay_us(unsigned char n); void init_NRF24L01(void); uint SPI_RW(uint uchar); uchar SPI_Read(uchar reg); void SetRX_Mode(void); uint SPI_RW_Reg(uchar reg, uchar value); uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf); //***************************************** 长 延 时 ***************************************** void Delay(unsigned int s) { unsigned int i; for(i=0; i<s; i++); for(i=0; i<s; i++); } //***************************************************************************** ************* uint bdata sta; //状态标志 sbit RX_DR =sta^6; sbit TX_DS =sta^5; sbit MAX_RT =sta^4; /****************************************************************************** ************ /*延时函数 /****************************************************************************** ************/ void inerDelay_us(unsigned char n) { for(;n>0;n--) _nop_(); } //***************************************************************************** *********** /*NRF24L01 初始化 //***************************************************************************** **********/ void init_NRF24L01(void) { inerDelay_us(100); CE=0; // chip enable CSN=1; // Spi disable SCK=0; // Spi clock line init high SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址 SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道 0 自动 ACK 应 答 允 许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道 0,如 果需要多频道可以参考 Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为 2.4GHZ, 收发必 须一致 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度, 本次设置为 32 字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为 1MHZ,发射 功率为最大值 0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ 收发完成中断响应,16 位 CRC,主发送 } /****************************************************************************** ********************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01 的 SPI 写时序 /****************************************************************************** **********************/ uint SPI_RW(uint uchar) { uint bit_ctr; for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit { MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); // shift next bit into MSB.. SCK = 1; // Set SCK high.. uchar |= MISO; // capture current MISO bit SCK = 0; // ..then set SCK low again } return(uchar); // return read uchar } /****************************************************************************** ********************** /*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01 的 SPI 时序 /****************************************************************************** **********************/ uchar SPI_Read(uchar reg) { uchar reg_val; CSN = 0; SPI_RW(reg); reg_val = SPI_RW(0); CSN = 1; // CSN low, initialize SPI communication... // Select register to read from.. // ..then read registervalue // CSN high, terminate SPI communication return(reg_val); // return register value } /****************************************************************************** **********************/ /*功能:NRF24L01 读写寄存器函数 /****************************************************************************** **********************/ uint SPI_RW_Reg(uchar reg, uchar value) { uint status; CSN = 0; status = SPI_RW(reg); SPI_RW(value); CSN = 1; return(status); // CSN low, init SPI transaction // select register // ..and write value to it.. // CSN high again // return nRF24L01 status uchar } /****************************************************************************** **********************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的 个数 /****************************************************************************** **********************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; status = SPI_RW(reg); // Set CSN low, init SPI tranaction // Select register to write to and read status uchar for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++) pBuf[uchar_ctr] = SPI_RW(0); // CSN = 1; return(status); // return nRF24L01 status uchar } /****************************************************************************** *************************** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数 /****************************************************************************** ***************************/ uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; //SPI 使能 status = SPI_RW(reg); for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) // SPI_RW(*pBuf++); CSN = 1; //关闭 SPI return(status); // } /****************************************************************************** **********************/ /*函数:void SetRX_Mode(void) /*功能:数据接收配置 /****************************************************************************** **********************/ void SetRX_Mode(void) { CE=0; SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ 收发完成中断响应,16 位 CRC ,主接收 CE = 1; inerDelay_us(130); } /****************************************************************************** ************************/ /*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放如 rx_buf 接收缓冲区中 /****************************************************************************** ************************/ unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) { unsigned char revale=0; sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况 if(RX_DR) // 判断是否接收到数据 { CE = 0; //SPI 使能 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer revale =1; //读取数据完成标志 } SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后 RX_DR,TX_DS,MAX_PT 都置高为 1,通过写 1 来清楚中断标志 return revale; } /****************************************************************************** ***************************** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf 中数据 /****************************************************************************** ****************************/ void nRF24L01_TxPacket(unsigned char * tx_buf) { CE=0; //StandBy I 模式 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址 SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装 载 数 据 // SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ 收发完成中断响应,16 位 CRC,主发送 CE=1; //置高 CE,激发数据发送 inerDelay_us(10); } //************************************ 主 函 数 ************************************************************ void main(void) { uchar temp =0; init_NRF24L01() ; led0=0;led1=0;led2=0;led3=0; P0=0x00; nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(6000); P0=0xBF; while(1) { if(temp<4) { switch(temp) { case 1: P0= 0xBF; break; case 2: P0= 0xf7; case break; 3: P0= 0xFE; break; default: break; } } if(temp==3) { temp=0; } nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(20000); SPI_RW_Reg(WRITE_REG+STATUS,0XFF); temp++; } }
#include <reg52.h> #include <intrins.h> typedef unsigned char uchar; typedef unsigned char uint; //****************************************IO 端 口 定 义 *************************************** sbit MISO =P1^2; sbit MOSI =P3^2; sbit SCK =P1^6; sbit CE =P1^5; sbit CSN =P1^7; sbit IRQ =P1^3; //*********************************** 数 码 管 0-9 编 码 ******************************************* uchar seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9 段码 uchar TxBuf[32]= { 0x01,0x02,0x03,0x4,0x05,0x06,0x07,0x08, 0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16, 0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24, 0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32, }; // //************************************ 按 键 ********************************************** sbit KEY1=P3^6; sbit KEY2=P3^7; //*********************************** 数 码 管 位 选 ************************************************** sbit led1=P2^1; sbit led0=P2^0; sbit led2=P2^2; sbit led3=P2^3; //*********************************************NRF24L01*********************** ************** #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5 // 5 uints RX address width #define TX_PLOAD_WIDTH 32 // 20 uints TX payload #define RX_PLOAD_WIDTH 32 // 20 uints TX payload uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址 //***************************************NRF24L01 寄 存 器 指 令 ******************************************************* #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送 FIFO 指令 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO 指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留 //*************************************SPI(nRF24L01) 寄 存 器 地 址 **************************************************** #define CONFIG 0x00 // 配置收发状态,CRC 校验模式以及收发状态响应方式 #define EN_AA 0x01 // 自动应答功能设置 #define EN_RXADDR 0x02 // 可用信道设置 #define SETUP_AW 0x03 // 收发地址宽度设置 #define SETUP_RETR 0x04 // 自动重发功能设置 #define RF_CH 0x05 // 工作频率设置 #define RF_SETUP 0x06 // 发射速率、功耗功能设置 #define STATUS 0x07 // 状态寄存器 #define OBSERVE_TX 0x08 // 发送监测功能 #define CD 0x09 // 地址检测 #define RX_ADDR_P0 0x0A // 频道 0 接收数据地址 #define RX_ADDR_P1 0x0B // 频道 1 接收数据地址 #define RX_ADDR_P2 0x0C // 频道 2 接收数据地址 #define RX_ADDR_P3 0x0D // 频道 3 接收数据地址 #define RX_ADDR_P4 0x0E // 频道 4 接收数据地址 #define RX_ADDR_P5 0x0F // 频道 5 接收数据地址 #define TX_ADDR 0x10 // 发送地址寄存器 #define RX_PW_P0 0x11 // 接收频道 0 接收数据长度 #define RX_PW_P1 0x12 // 接收频道 0 接收数据长度 #define RX_PW_P2 0x13 // 接收频道 0 接收数据长度 #define RX_PW_P3 0x14 // 接收频道 0 接收数据长度 #define RX_PW_P4 0x15 // 接收频道 0 接收数据长度 #define RX_PW_P5 0x16 // 接收频道 0 接收数据长度 #define FIFO_STATUS 0x17 // FIFO 栈入栈出状态寄存器设置 //***************************************************************************** ********* void Delay(unsigned int s); void inerDelay_us(unsigned char n); void init_NRF24L01(void); uint SPI_RW(uint uchar); uchar SPI_Read(uchar reg); void SetRX_Mode(void); uint SPI_RW_Reg(uchar reg, uchar value); uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf); //***************************************** 长 延 时 ***************************************** void Delay(unsigned int s) { unsigned int i; for(i=0; i<s; i++); for(i=0; i<s; i++); } //***************************************************************************** ************* uint bdata sta; //状态标志 sbit RX_DR =sta^6; sbit TX_DS =sta^5; sbit MAX_RT =sta^4; /****************************************************************************** ************ /*延时函数 /****************************************************************************** ************/ void inerDelay_us(unsigned char n) { for(;n>0;n--) _nop_(); } //***************************************************************************** *********** /*NRF24L01 初始化 //***************************************************************************** **********/ void init_NRF24L01(void) { inerDelay_us(100); CE=0; // chip enable CSN=1; // Spi disable SCK=0; // Spi clock line init high SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址 SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道 0 自动 ACK 应 答 允 许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道 0,如 果需要多频道可以参考 Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为 2.4GHZ, 收发必 须一致 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度, 本次设置为 32 字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为 1MHZ,发射 功率为最大值 0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ 收发完成中断响应,16 位 CRC,主发送 } /****************************************************************************** ********************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01 的 SPI 写时序 /****************************************************************************** **********************/ uint SPI_RW(uint uchar) { uint bit_ctr; for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit { MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); // shift next bit into MSB.. SCK = 1; // Set SCK high.. uchar |= MISO; // capture current MISO bit SCK = 0; // ..then set SCK low again } return(uchar); // return read uchar } /****************************************************************************** ********************** /*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01 的 SPI 时序 /****************************************************************************** **********************/ uchar SPI_Read(uchar reg) { uchar reg_val; CSN = 0; SPI_RW(reg); reg_val = SPI_RW(0); CSN = 1; // CSN low, initialize SPI communication... // Select register to read from.. // ..then read registervalue // CSN high, terminate SPI communication return(reg_val); // return register value } /****************************************************************************** **********************/ /*功能:NRF24L01 读写寄存器函数 /****************************************************************************** **********************/ uint SPI_RW_Reg(uchar reg, uchar value) { uint status; CSN = 0; status = SPI_RW(reg); SPI_RW(value); CSN = 1; return(status); // CSN low, init SPI transaction // select register // ..and write value to it.. // CSN high again // return nRF24L01 status uchar } /****************************************************************************** **********************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的 个数 /****************************************************************************** **********************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; status = SPI_RW(reg); // Set CSN low, init SPI tranaction // Select register to write to and read status uchar for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++) pBuf[uchar_ctr] = SPI_RW(0); // CSN = 1; return(status); // return nRF24L01 status uchar } /****************************************************************************** *************************** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数 /****************************************************************************** ***************************/ uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) { uint status,uchar_ctr; CSN = 0; //SPI 使能 status = SPI_RW(reg); for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) // SPI_RW(*pBuf++); CSN = 1; //关闭 SPI return(status); // } /****************************************************************************** **********************/ /*函数:void SetRX_Mode(void) /*功能:数据接收配置 /****************************************************************************** **********************/ void SetRX_Mode(void) { CE=0; SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ 收发完成中断响应,16 位 CRC ,主接收 CE = 1; inerDelay_us(130); } /****************************************************************************** ************************/ /*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放如 rx_buf 接收缓冲区中 /****************************************************************************** ************************/ unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) { unsigned char revale=0; sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况 if(RX_DR) // 判断是否接收到数据 { CE = 0; //SPI 使能 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer revale =1; //读取数据完成标志 } SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后 RX_DR,TX_DS,MAX_PT 都置高为 1,通过写 1 来清楚中断标志 return revale; } /****************************************************************************** ***************************** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf 中数据 /****************************************************************************** ****************************/ void nRF24L01_TxPacket(unsigned char * tx_buf) { CE=0; //StandBy I 模式 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址 SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装 载 数 据 // SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ 收发完成中断响应,16 位 CRC,主发送 CE=1; //置高 CE,激发数据发送 inerDelay_us(10); } //************************************ 主 函 数 ************************************************************ void main(void) { uchar temp =0; init_NRF24L01() ; led0=0;led1=0;led2=0;led3=0; P0=0x00; nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(6000); P0=0xBF; while(1) { if(temp<4) { switch(temp) { case 1: P0= 0xBF; break; case 2: P0= 0xf7; case break; 3: P0= 0xFE; break; default: break; } } if(temp==3) { temp=0; } nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data Delay(20000); SPI_RW_Reg(WRITE_REG+STATUS,0XFF); temp++; } }
展开全部
不是你的NRF24L01,希望对你有点用
CONTROLLER_BASE EQU 7E00H ;SJA1000的片选地址
RCV_GOOD BIT 0FH ;成功的接收一帧标志
SEC_FLAG BIT 010H ;一秒到标志
ERR_FLAG BIT 011H ;监测到错误标志
SAVE_INT_INFO DATA 032H ;保存SJA1000中断寄存器的内容
SEND_DATA_BUF1 DATA 040H ;发送缓冲区
SEND_DATA_BUF2 DATA 041H
SEND_DATA_BUF3 DATA 042H
SEND_DATA_BUF4 DATA 043H
SEND_DATA_BUF5 DATA 044H
SEND_DATA_BUF6 DATA 045H
SEND_DATA_BUF7 DATA 046H
SEND_DATA_BUF8 DATA 047H
SEND_DATA_BUF9 DATA 048H
SEND_DATA_BUF10 DATA 049H
RCV_DATA_BUF1 DATA 050H ;接收缓冲区
RCV_DATA_BUF2 DATA 051H
RCV_DATA_BUF3 DATA 052H
RCV_DATA_BUF4 DATA 053H
RCV_DATA_BUF5 DATA 054H
RCV_DATA_BUF6 DATA 055H
RCV_DATA_BUF7 DATA 056H
RCV_DATA_BUF8 DATA 057H
RCV_DATA_BUF9 DATA 058H
RCV_DATA_BUF10 DATA 059H
ERROR_STATUS DATA 07CH ;错误状态表示
TEST_DATA DATA 07FH ;测试发送数据
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;程序开始
ORG 0000H
LJMP MAIN ;运行主程序
ORG 0003H
LJMP BCAN_INT0 ;中断方式访问SJA1000程序
ORG 000BH
LJMP T0_INTERRUPT ;定时器0中断
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0100H ;程序开始
MAIN:
MOV R0,#07fH
CLR A
MOV @R0,A
DJNZ R0,$-1
MOV @R0,A
MOV SP,#60H ;设置SP
CLR P2.0 ;SJA1000退出硬件复位模式
LCALL SJA1000_INT0 ;初始化SJA1000
LCALL T0_INIT
CLR P3.4 ;点亮指示灯
SETB PX0
SETB IT0
SETB EX0
SETB ET0
SETB TR0
SETB EA
LOOPER:
JNB RCV_GOOD,LOOPER2 ;sja1000成功接收一帧,通知CPU处理
CLR RCV_GOOD
LCALL RCVDATA_PRG
LOOPER2:
JNB SEC_FLAG,LOOPER3 ;一秒时间到,每秒发送一次
CLR SEC_FLAG
CLR P3.5 ;点亮指示灯
LCALL SENDDATA_PRG
LOOPER3:
JNB ERR_FLAG,LOOPER4 ;错误标志,错误处理
CLR ERR_FLAG
LCALL ERR_PRG
LOOPER4:
AJMP LOOPER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;初始化SJA1000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SJA1000_INT0:
LCALL BCAN_CREATE_COMMUNATION ;调用SJA1000接口测试函数
MOV R7, #04
LCALL BCAN_SET_BANDRATE ;设置波特率为100k
MOV R7, #0A8H ;设置接收报文ID
MOV R6, #0FFH
LCALL BCAN_SET_OBJECT
MOV R7, #0AAH ;设置输出控制、时钟分频;正常输出模式
MOV R6, #048H ;使能内部比较器、禁止CLKOUT
LCALL BCAN_SET_OUTCLK ;
LCALL BCAN_QUIT_RETMODEL ;退出复位状态
MOV DPTR,#REG_CONTROL ;开放SJA1000内部功能中断
MOV A,#01EH ;中断开放
MOVX @DPTR,A
CLR F0
RET
;;;;;;;;;;;;;;;;;;;;;;错误信息处理;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ERR_PRG:
LCALL BCAN_ENTER_RETMODEL ;进入复位模式
LCALL SJA1000_INT0 ;
MOV ERROR_STATUS,#0FCH
RET
;;;;;;;;;;;;;;;;;;;;;;;接收数据处理部分;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RCVDATA_PRG:
MOV R0,# RCV_DATA_BUF1 ;微处理器接收首地址
LCALL BCAN_DATA_RECEIVE ;调用接收数据子程序
MOV R7,#04H ;释放接收缓冲区
LCALL BCAN_CMD_PRG ;
RET
;;;;;;;;;;;;;;;;;;控制SJA1000向CAN总线发送数据处理部分;;;;;;;;;;;;;;;
SENDDATA_PRG:
MOV R0, #SEND_DATA_BUF1
MOV @R0, #02H
INC R0
MOV @R0, #08H
INC R0
MOV @R0, #05H
MOV A, TEST_DATA
INC R0
MOV @R0, A
MOV R0, #SEND_DATA_BUF1
LCALL BCAN_DATA_WRITE ;将要发送的数据送入发送缓冲区
MOV R7, #01
LCALL BCAN_CMD_PRG
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定时器0初始化;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
T0_INIT:
MOV A,TMOD
ANL A,#0F0H
ORL A,#01H
MOV TMOD,A;T0工作在方式1
MOV TH0,#0FCH ;定时周期1MS
MOV TL0,#066H
MOV 3AH,#00H
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;外部中断0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BCAN_INT0:
push DPH
PUSH DPL
PUSH PSW ;PSW,ACC入栈
PUSH ACC
USING 3 ;应用寄存器第3组
MOV DPTR,#REG_INTERRUPT ;读中断寄存器
MOVX A,@DPTR ;
MOV SAVE_INT_INFO,A ;保存中断寄存器的内容
JNB ACC.0,BCAN_INT1 ;接收中断
SETB RCV_GOOD ;置位接收标志
BCAN_INT1:
MOV A,SAVE_INT_INFO
JNB ACC.2,BCAN_INT2 ;错误中断
SETB ERR_FLAG ;置位错误标志
BCAN_INT2:
POP ACC
POP PSW
POP DPL
POP DPH
RETI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定时器0中断;;;;;;;;;;;;;;;;
T0_INTERRUPT:
push DPH
PUSH DPL
PUSH PSW ;PSW、ACC入栈
PUSH ACC
USING 2
MOV TH0,#80H ;设置定时周期0.3S
MOV TL0,#26H
INC 3AH
MOV A,3AH
CJNE A,#23H,T0_QUIT ;判断1秒时间是否到
MOV 3AH,#00H
INC TEST_DATA ;测试发送的数据,每1秒加1
SETB SEC_FLAG ;置位1秒到标志
T0_QUIT:
POP ACC
POP PSW
POP DPL
POP DPH
RETI
BCAN_ENTER_RETMODEL:
MOV DPTR, #REG_CONTROL ;控制寄存器访问
MOVX A, @DPTR ;
ORL A, #01H ;置位复位请求
MOVX @DPTR, A ;
CLR F0
MOVX A, @DPTR ;验证复位是否写入
JB ACC.0, BCAN_ER_QUIT
SETB F0 ;复位不成功
BCAN_ER_QUIT:
RET
BCAN_QUIT_RETMODEL:
MOV DPTR, #REG_CONTROL ; 控制寄存器访问
MOVX A, @DPTR ;
ANL A, #0FEH ;清零复位请求,进入工作状态
MOVX @DPTR, A
CLR F0
MOVX A, @DPTR
JNB ACC.0, BCAN_QR_QUIT ;验证是否退出复位状态
SETB F0
BCAN_QR_QUIT:
RET
BCAN_DATA_WRITE:
MOV DPTR, #REG_STATUS ;读取状态寄存器
MOVX A, @DPTR ;判断上次发送是否完成
SETB F0
JNB ACC.3, BCAN_DW_QUIT ;正在发送退出
CLR F0
MOVX A, @DPTR ;判断发送缓冲区是否锁定,
SETB F0
JNB ACC.2, BCAN_DW_QUIT ;锁定则跳出
CLR F0
INC R0 ;
MOV A, @R0 ;ID号的低3位 RTR位 数据长度DLC
DEC R0 ;恢复指针指向发送数据的首地址
MOV DPTR, #REG_TxBuffer1;发送缓冲区首地址
JB ACC.4, BCAN_WYB ;远程帧
;数据帧
ANL A, #0FH ;计算发送数据的长度
ADD A, #02H
MOV R7, A
AJMP BCAN_WRTXBUF ;
BCAN_WYB:
MOV R7, #02 ;写入发送缓冲区数据长度为2
BCAN_WRTXBUF:
MOV A, @R0 ;开始写入
MOVX @DPTR, A
SETB F0
MOVX A, @DPTR ;校验写入的是否正确
XRL A, @R0
JNZ BCAN_DW_QUIT ;写入错误退出
CLR F0 ;正确写入继续
INC R0
INC DPTR
DJNZ R7, BCAN_WRTXBUF ;没有写完继续
BCAN_DW_QUIT:
RET
BCAN_DATA_RECEIVE:
MOV DPTR, #REG_STATUS
MOVX A, @DPTR
SETB F0
JNB ACC.0, BCAN_DR_QUIT ;判断报文是否有效
CLR F0
MOV DPTR, #REG_RxBuffer2 ;接收报文的ID号的低3位 RTR位 数据长度DLC
MOVX A, @DPTR
MOV DPTR, #REG_RxBuffer1 ;接收缓冲区的首地址
JB ACC.4, BCAN_RCVYB ;接收到的是远程帧
;数据帧
ANL A, #0FH ;计算接收到的数据长度
ADD A, #02H ;计算报文的长度
MOV R6, A
AJMP BCAN_RCVDATA
BCAN_RCVYB:
MOV R6, #02 ;远程帧
BCAN_RCVDATA: ;开始读取数据
MOVX A, @DPTR
MOV @R0, A
INC DPTR
INC R0
DJNZ R6, BCAN_RCVDATA
BCAN_DR_QUIT:
RET
BCAN_SET_BANDRATE:
MOV A, R7 ;判断波特率的值是否存在
CLR CY
SUBB A, #13 ;
SETB F0
JNC BCAN_SETBR_QUIT ;输入的值大于12则不正确
CLR F0
MOV A, R7
RL A
MOV DPTR, #BCAN_SETBR ;查表找出相应的预设第一个值
MOVC A, @A+DPTR
MOV R5, A ;将数据保存
MOV A, R7 ;找出第二个值
RL A
INC A
MOVC A, @A+DPTR
MOV R6, A ;保存值
MOV DPTR, #REG_BTR0 ;装入波特率预设值,同步跳转宽度
;位宽度
MOV A, R5
MOVX @DPTR, A
SETB F0
MOVX A, @DPTR
XRL A, R5 ;判断写入是否正确
JNZ BCAN_SETBR_QUIT ;不正确
CLR F0
INC DPTR
MOV A, R6
MOVX @DPTR, A
SETB F0
MOVX A, @DPTR
XRL A, R6 ;判断写入是否正确
JNZ BCAN_SETBR_QUIT
CLR F0
BCAN_SETBR_QUIT:
RET
BCAN_SETBR:
DB 053H, 02FH ;20KBPS的预设值
DB 087H, 0FFH ;40KBPS的预设值
DB 047H, 02FH ;50KBPS的预设值
DB 083H, 0FFH ;80KBPS的预设值
DB 043H, 02fH ;100KBPS的预设值
DB 03H, 01cH ;125KBPS的预设值
DB 081H, 0faH ;200KBPS的预设值
DB 01H, 01cH ;250KBPS的预设值
DB 080H, 0faH ;400KBPS的预设值
DB 00H, 01cH ;500KBPS的预设值
DB 080H, 0b6H ;666KBPS的预设值
DB 00H, 016H ;800KBPS的预设值
DB 00H, 014H ;1000KBPS的预设值
BCAN_SET_OBJECT:
MOV DPTR, #REG_ACR ;写ACR寄存器
MOV A, R7
MOVX @DPTR, A
MOVX A, @DPTR
SETB F0
XRL A, R7 ;检验写入是否正确
JNZ BCAN_SETO_QUIT
CLR F0
INC DPTR ;写AMR寄存器
MOV A, R6
MOVX @DPTR, A
MOVX A, @DPTR
SETB F0
XRL A, R6 ;检验写入是否正确
JNZ BCAN_SETO_QUIT
CLR F0
BCAN_SETO_QUIT:
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BCAN_CMD_PRG:
MOV A, R7
CJNE A, #01, BCAN_CMD1
;发送请求命令
MOV DPTR, #REG_COMMAND; 地址指向命令寄存器
MOVX @DPTR, A ;写入命令字
CLR F0
RET
BCAN_CMD1:
CJNE A, #02, BCAN_CMD2
;;//夭折发送命令
MOV DPTR, #REG_STATUS ;地址指向状态寄存器
MOVX A, @DPTR ;判断是否有正在发送的状态
SETB F0
JB ACC.5, BCAN_CMD_QUIT
CLR F0
BCAN_CMD_QUIT:
RET
CAN开发板使用说明
1、 实验板分为主节点和从节点;CAN通讯波特率设置为800K;最高可设置为1M,用户根据自己的需要进行设置.
2、 从节点每隔2.25秒钟向主节点发送一组8个字节的数据,数据格式为:05H i 00H 00H 00H 00H 00H 00H ;其中变量I的范围是00H~FFH,他随着每发送一次数据而累加递增1;从节点指示灯1表示实验板工作正常,指示灯2以0.44Hz的频率闪烁,表示发送数据正常.
3、 主节点的ID为550,每当收到从节点发送的数据后,主节点便以9.6K波特率把收到的数据通过232串口发送给计算机,计算机上安装的用户界面(串口调试助手),可以实时显示接收到的数据,此数据用户可以存储于计算机上;主节点指示灯1表示实验板工作正常,指示灯2以1Hz的频率闪烁(如果是调用c语言程序,则以0.44Hz频率闪烁),表示接收和串口发送数据正常.
4、 单片机为AT89c51,适用于实验板(电源没有隔离); 主控单片机为ADuC812,适用于工程应用(电源隔离):ADuC812通过自带的12位精度的A/D采集传感器信号后,将采集结果通过can总线传输到“主控节点”,主控节点将数据通过串口传输给计算机;指示灯显示状态;可以通过串口给主控节点发送指令,来完成对某一节点的控制;通过串口下载程序到单片机ADuC812(详见ADuC812用户手册),可以不用编程器;
5、 串口调试助手的页面设置详见下图所示:
用户严格按照上图所示进行设置;
6、使用CAN开发板的用户请务必注意以下事项:
A、开发板的供电电压为12V,插头处有+12V和GND标志;
B、SJA1000的地址为0X7E00;
C、注意P2_0=0;以便使SJA1000退出复位状态;
D、主节点的地址为550,通讯波特率为800K;
E、RS232串口三根线说明:白色线为地线;红色线为发送线;黑色线为接收线;
感谢您选用CAN开发板!真诚的希望您在短时间内掌握CAN的基本知识,如有任何问题请发至nnyt@tom.com,我将尽快给您答复;
CONTROLLER_BASE EQU 7E00H ;SJA1000的片选地址
RCV_GOOD BIT 0FH ;成功的接收一帧标志
SEC_FLAG BIT 010H ;一秒到标志
ERR_FLAG BIT 011H ;监测到错误标志
SAVE_INT_INFO DATA 032H ;保存SJA1000中断寄存器的内容
SEND_DATA_BUF1 DATA 040H ;发送缓冲区
SEND_DATA_BUF2 DATA 041H
SEND_DATA_BUF3 DATA 042H
SEND_DATA_BUF4 DATA 043H
SEND_DATA_BUF5 DATA 044H
SEND_DATA_BUF6 DATA 045H
SEND_DATA_BUF7 DATA 046H
SEND_DATA_BUF8 DATA 047H
SEND_DATA_BUF9 DATA 048H
SEND_DATA_BUF10 DATA 049H
RCV_DATA_BUF1 DATA 050H ;接收缓冲区
RCV_DATA_BUF2 DATA 051H
RCV_DATA_BUF3 DATA 052H
RCV_DATA_BUF4 DATA 053H
RCV_DATA_BUF5 DATA 054H
RCV_DATA_BUF6 DATA 055H
RCV_DATA_BUF7 DATA 056H
RCV_DATA_BUF8 DATA 057H
RCV_DATA_BUF9 DATA 058H
RCV_DATA_BUF10 DATA 059H
ERROR_STATUS DATA 07CH ;错误状态表示
TEST_DATA DATA 07FH ;测试发送数据
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;程序开始
ORG 0000H
LJMP MAIN ;运行主程序
ORG 0003H
LJMP BCAN_INT0 ;中断方式访问SJA1000程序
ORG 000BH
LJMP T0_INTERRUPT ;定时器0中断
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0100H ;程序开始
MAIN:
MOV R0,#07fH
CLR A
MOV @R0,A
DJNZ R0,$-1
MOV @R0,A
MOV SP,#60H ;设置SP
CLR P2.0 ;SJA1000退出硬件复位模式
LCALL SJA1000_INT0 ;初始化SJA1000
LCALL T0_INIT
CLR P3.4 ;点亮指示灯
SETB PX0
SETB IT0
SETB EX0
SETB ET0
SETB TR0
SETB EA
LOOPER:
JNB RCV_GOOD,LOOPER2 ;sja1000成功接收一帧,通知CPU处理
CLR RCV_GOOD
LCALL RCVDATA_PRG
LOOPER2:
JNB SEC_FLAG,LOOPER3 ;一秒时间到,每秒发送一次
CLR SEC_FLAG
CLR P3.5 ;点亮指示灯
LCALL SENDDATA_PRG
LOOPER3:
JNB ERR_FLAG,LOOPER4 ;错误标志,错误处理
CLR ERR_FLAG
LCALL ERR_PRG
LOOPER4:
AJMP LOOPER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;初始化SJA1000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SJA1000_INT0:
LCALL BCAN_CREATE_COMMUNATION ;调用SJA1000接口测试函数
MOV R7, #04
LCALL BCAN_SET_BANDRATE ;设置波特率为100k
MOV R7, #0A8H ;设置接收报文ID
MOV R6, #0FFH
LCALL BCAN_SET_OBJECT
MOV R7, #0AAH ;设置输出控制、时钟分频;正常输出模式
MOV R6, #048H ;使能内部比较器、禁止CLKOUT
LCALL BCAN_SET_OUTCLK ;
LCALL BCAN_QUIT_RETMODEL ;退出复位状态
MOV DPTR,#REG_CONTROL ;开放SJA1000内部功能中断
MOV A,#01EH ;中断开放
MOVX @DPTR,A
CLR F0
RET
;;;;;;;;;;;;;;;;;;;;;;错误信息处理;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ERR_PRG:
LCALL BCAN_ENTER_RETMODEL ;进入复位模式
LCALL SJA1000_INT0 ;
MOV ERROR_STATUS,#0FCH
RET
;;;;;;;;;;;;;;;;;;;;;;;接收数据处理部分;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RCVDATA_PRG:
MOV R0,# RCV_DATA_BUF1 ;微处理器接收首地址
LCALL BCAN_DATA_RECEIVE ;调用接收数据子程序
MOV R7,#04H ;释放接收缓冲区
LCALL BCAN_CMD_PRG ;
RET
;;;;;;;;;;;;;;;;;;控制SJA1000向CAN总线发送数据处理部分;;;;;;;;;;;;;;;
SENDDATA_PRG:
MOV R0, #SEND_DATA_BUF1
MOV @R0, #02H
INC R0
MOV @R0, #08H
INC R0
MOV @R0, #05H
MOV A, TEST_DATA
INC R0
MOV @R0, A
MOV R0, #SEND_DATA_BUF1
LCALL BCAN_DATA_WRITE ;将要发送的数据送入发送缓冲区
MOV R7, #01
LCALL BCAN_CMD_PRG
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定时器0初始化;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
T0_INIT:
MOV A,TMOD
ANL A,#0F0H
ORL A,#01H
MOV TMOD,A;T0工作在方式1
MOV TH0,#0FCH ;定时周期1MS
MOV TL0,#066H
MOV 3AH,#00H
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;外部中断0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BCAN_INT0:
push DPH
PUSH DPL
PUSH PSW ;PSW,ACC入栈
PUSH ACC
USING 3 ;应用寄存器第3组
MOV DPTR,#REG_INTERRUPT ;读中断寄存器
MOVX A,@DPTR ;
MOV SAVE_INT_INFO,A ;保存中断寄存器的内容
JNB ACC.0,BCAN_INT1 ;接收中断
SETB RCV_GOOD ;置位接收标志
BCAN_INT1:
MOV A,SAVE_INT_INFO
JNB ACC.2,BCAN_INT2 ;错误中断
SETB ERR_FLAG ;置位错误标志
BCAN_INT2:
POP ACC
POP PSW
POP DPL
POP DPH
RETI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定时器0中断;;;;;;;;;;;;;;;;
T0_INTERRUPT:
push DPH
PUSH DPL
PUSH PSW ;PSW、ACC入栈
PUSH ACC
USING 2
MOV TH0,#80H ;设置定时周期0.3S
MOV TL0,#26H
INC 3AH
MOV A,3AH
CJNE A,#23H,T0_QUIT ;判断1秒时间是否到
MOV 3AH,#00H
INC TEST_DATA ;测试发送的数据,每1秒加1
SETB SEC_FLAG ;置位1秒到标志
T0_QUIT:
POP ACC
POP PSW
POP DPL
POP DPH
RETI
BCAN_ENTER_RETMODEL:
MOV DPTR, #REG_CONTROL ;控制寄存器访问
MOVX A, @DPTR ;
ORL A, #01H ;置位复位请求
MOVX @DPTR, A ;
CLR F0
MOVX A, @DPTR ;验证复位是否写入
JB ACC.0, BCAN_ER_QUIT
SETB F0 ;复位不成功
BCAN_ER_QUIT:
RET
BCAN_QUIT_RETMODEL:
MOV DPTR, #REG_CONTROL ; 控制寄存器访问
MOVX A, @DPTR ;
ANL A, #0FEH ;清零复位请求,进入工作状态
MOVX @DPTR, A
CLR F0
MOVX A, @DPTR
JNB ACC.0, BCAN_QR_QUIT ;验证是否退出复位状态
SETB F0
BCAN_QR_QUIT:
RET
BCAN_DATA_WRITE:
MOV DPTR, #REG_STATUS ;读取状态寄存器
MOVX A, @DPTR ;判断上次发送是否完成
SETB F0
JNB ACC.3, BCAN_DW_QUIT ;正在发送退出
CLR F0
MOVX A, @DPTR ;判断发送缓冲区是否锁定,
SETB F0
JNB ACC.2, BCAN_DW_QUIT ;锁定则跳出
CLR F0
INC R0 ;
MOV A, @R0 ;ID号的低3位 RTR位 数据长度DLC
DEC R0 ;恢复指针指向发送数据的首地址
MOV DPTR, #REG_TxBuffer1;发送缓冲区首地址
JB ACC.4, BCAN_WYB ;远程帧
;数据帧
ANL A, #0FH ;计算发送数据的长度
ADD A, #02H
MOV R7, A
AJMP BCAN_WRTXBUF ;
BCAN_WYB:
MOV R7, #02 ;写入发送缓冲区数据长度为2
BCAN_WRTXBUF:
MOV A, @R0 ;开始写入
MOVX @DPTR, A
SETB F0
MOVX A, @DPTR ;校验写入的是否正确
XRL A, @R0
JNZ BCAN_DW_QUIT ;写入错误退出
CLR F0 ;正确写入继续
INC R0
INC DPTR
DJNZ R7, BCAN_WRTXBUF ;没有写完继续
BCAN_DW_QUIT:
RET
BCAN_DATA_RECEIVE:
MOV DPTR, #REG_STATUS
MOVX A, @DPTR
SETB F0
JNB ACC.0, BCAN_DR_QUIT ;判断报文是否有效
CLR F0
MOV DPTR, #REG_RxBuffer2 ;接收报文的ID号的低3位 RTR位 数据长度DLC
MOVX A, @DPTR
MOV DPTR, #REG_RxBuffer1 ;接收缓冲区的首地址
JB ACC.4, BCAN_RCVYB ;接收到的是远程帧
;数据帧
ANL A, #0FH ;计算接收到的数据长度
ADD A, #02H ;计算报文的长度
MOV R6, A
AJMP BCAN_RCVDATA
BCAN_RCVYB:
MOV R6, #02 ;远程帧
BCAN_RCVDATA: ;开始读取数据
MOVX A, @DPTR
MOV @R0, A
INC DPTR
INC R0
DJNZ R6, BCAN_RCVDATA
BCAN_DR_QUIT:
RET
BCAN_SET_BANDRATE:
MOV A, R7 ;判断波特率的值是否存在
CLR CY
SUBB A, #13 ;
SETB F0
JNC BCAN_SETBR_QUIT ;输入的值大于12则不正确
CLR F0
MOV A, R7
RL A
MOV DPTR, #BCAN_SETBR ;查表找出相应的预设第一个值
MOVC A, @A+DPTR
MOV R5, A ;将数据保存
MOV A, R7 ;找出第二个值
RL A
INC A
MOVC A, @A+DPTR
MOV R6, A ;保存值
MOV DPTR, #REG_BTR0 ;装入波特率预设值,同步跳转宽度
;位宽度
MOV A, R5
MOVX @DPTR, A
SETB F0
MOVX A, @DPTR
XRL A, R5 ;判断写入是否正确
JNZ BCAN_SETBR_QUIT ;不正确
CLR F0
INC DPTR
MOV A, R6
MOVX @DPTR, A
SETB F0
MOVX A, @DPTR
XRL A, R6 ;判断写入是否正确
JNZ BCAN_SETBR_QUIT
CLR F0
BCAN_SETBR_QUIT:
RET
BCAN_SETBR:
DB 053H, 02FH ;20KBPS的预设值
DB 087H, 0FFH ;40KBPS的预设值
DB 047H, 02FH ;50KBPS的预设值
DB 083H, 0FFH ;80KBPS的预设值
DB 043H, 02fH ;100KBPS的预设值
DB 03H, 01cH ;125KBPS的预设值
DB 081H, 0faH ;200KBPS的预设值
DB 01H, 01cH ;250KBPS的预设值
DB 080H, 0faH ;400KBPS的预设值
DB 00H, 01cH ;500KBPS的预设值
DB 080H, 0b6H ;666KBPS的预设值
DB 00H, 016H ;800KBPS的预设值
DB 00H, 014H ;1000KBPS的预设值
BCAN_SET_OBJECT:
MOV DPTR, #REG_ACR ;写ACR寄存器
MOV A, R7
MOVX @DPTR, A
MOVX A, @DPTR
SETB F0
XRL A, R7 ;检验写入是否正确
JNZ BCAN_SETO_QUIT
CLR F0
INC DPTR ;写AMR寄存器
MOV A, R6
MOVX @DPTR, A
MOVX A, @DPTR
SETB F0
XRL A, R6 ;检验写入是否正确
JNZ BCAN_SETO_QUIT
CLR F0
BCAN_SETO_QUIT:
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BCAN_CMD_PRG:
MOV A, R7
CJNE A, #01, BCAN_CMD1
;发送请求命令
MOV DPTR, #REG_COMMAND; 地址指向命令寄存器
MOVX @DPTR, A ;写入命令字
CLR F0
RET
BCAN_CMD1:
CJNE A, #02, BCAN_CMD2
;;//夭折发送命令
MOV DPTR, #REG_STATUS ;地址指向状态寄存器
MOVX A, @DPTR ;判断是否有正在发送的状态
SETB F0
JB ACC.5, BCAN_CMD_QUIT
CLR F0
BCAN_CMD_QUIT:
RET
CAN开发板使用说明
1、 实验板分为主节点和从节点;CAN通讯波特率设置为800K;最高可设置为1M,用户根据自己的需要进行设置.
2、 从节点每隔2.25秒钟向主节点发送一组8个字节的数据,数据格式为:05H i 00H 00H 00H 00H 00H 00H ;其中变量I的范围是00H~FFH,他随着每发送一次数据而累加递增1;从节点指示灯1表示实验板工作正常,指示灯2以0.44Hz的频率闪烁,表示发送数据正常.
3、 主节点的ID为550,每当收到从节点发送的数据后,主节点便以9.6K波特率把收到的数据通过232串口发送给计算机,计算机上安装的用户界面(串口调试助手),可以实时显示接收到的数据,此数据用户可以存储于计算机上;主节点指示灯1表示实验板工作正常,指示灯2以1Hz的频率闪烁(如果是调用c语言程序,则以0.44Hz频率闪烁),表示接收和串口发送数据正常.
4、 单片机为AT89c51,适用于实验板(电源没有隔离); 主控单片机为ADuC812,适用于工程应用(电源隔离):ADuC812通过自带的12位精度的A/D采集传感器信号后,将采集结果通过can总线传输到“主控节点”,主控节点将数据通过串口传输给计算机;指示灯显示状态;可以通过串口给主控节点发送指令,来完成对某一节点的控制;通过串口下载程序到单片机ADuC812(详见ADuC812用户手册),可以不用编程器;
5、 串口调试助手的页面设置详见下图所示:
用户严格按照上图所示进行设置;
6、使用CAN开发板的用户请务必注意以下事项:
A、开发板的供电电压为12V,插头处有+12V和GND标志;
B、SJA1000的地址为0X7E00;
C、注意P2_0=0;以便使SJA1000退出复位状态;
D、主节点的地址为550,通讯波特率为800K;
E、RS232串口三根线说明:白色线为地线;红色线为发送线;黑色线为接收线;
感谢您选用CAN开发板!真诚的希望您在短时间内掌握CAN的基本知识,如有任何问题请发至nnyt@tom.com,我将尽快给您答复;
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询