断断续续,零星学习这个
首先,在SJA1000+STC89C52硬件电路上,来回折腾近好久
本来是想着开发板+TJA1050模块,用杜邦线链接,先实现自收发。
结果死活不会自收发,没办法,只能去掏了2块CAN开发板.
总算有点进度,记录如下:
(1-期间,重新拜读了吴坚鸿大神的源码,并且使用了相关按键和数码管部分的源码)
出现了一直很神奇的现象,不知道缘由,待高手路过指点一下
我先说下现象情况
原来单片机开发板程序 显示的数字相同, 改了之后,显示收的数字比发大了1。
一步步的替换也试过,按键部分替换后正常,就是替换到数码管部分:
按第一下后,发的数字是1 ,收的数字还是0,再按一后,发的数字是2,收的数字成了1,
(原先是:按一下后,发的数字是1,收的数字也是1.)
首先是源程序
/*************************************************
*功能: CEPARK CAN开发板-CAN自收发实验
*说明:数码管从右到左分别是1~4位。
* 数码管1、2位显示发送的数据,3、4位显示接收到的数据。
* 每按一次中断按键发送数据值增一。
*芯片:STC89C52RC
*跳线:无
****************************************************/
#include <reg52.h>
#include "sjapelican.h"
#include "config.h"
//INT0按键为计数按键
void INT0_Data(void) interrupt 0
{
EA = 0;
Txd_data++; //存储计数结果,并为待发送的数据
Peli_TXD();
EA = 1;
}
//接收数据函数,在中断服务程序中调用
void Peli_RXD(void) interrupt 2
{
uint8 data Status;
EA = 0;//关CPU中断
Status = SJA_IR;
if(Status & RI_BIT)
{//IR.0 = 1 接收中断
RX_buffer[0] = SJA_RBSR0;
RX_buffer[1] = SJA_RBSR1;
RX_buffer[2] = SJA_RBSR2;
RX_buffer[3] = SJA_RBSR3;
RX_buffer[4] = SJA_RBSR4;
RX_buffer[5] = SJA_RBSR5;
RX_buffer[6] = SJA_RBSR6;
RX_buffer[7] = SJA_RBSR7;
RX_buffer[8] = SJA_RBSR8;
RX_buffer[9] = SJA_RBSR9;
RX_buffer[10] = SJA_RBSR10;
RX_buffer[11] = SJA_RBSR11;
RX_buffer[12] = SJA_RBSR12;
SJA_CMR = RRB_BIT;
Status = SJA_ALC;//释放仲裁随时捕捉寄存器
Status = SJA_ECC;//释放错误代码捕捉寄存器
}
SJA_IER = RIE_BIT;// .0=1--接收中断使能;
Rxd_data = RX_buffer[5];
EA = 1;//打开CPU中断
}
//CPU初始化
void MCU_Init(void)
{
SJA_RST = 0;//SJA1000复位有效
mDelay(10); //延时
SJA_RST = 1;//CAN总线复位管脚,复位无效
SJA_CS = 0;//CAN总线片选有效
EX1 = 1;//外部中断1使能;CAN总线接收中断
IT1 = 0;//CAN总线接收中断,低电平触发
IT0 = 1;//外部中断0负边沿触发
EX0 = 1;//打开外部中断0
EA = 1; //打开总中断
}
//主函数
void main(void)
{
MCU_Init();
Peli_Init();
// mDelay(1);
while(1) LED_Disp_Seg7(); //数码管显示函数
}
//SJA1000 的初始化
void Peli_Init(void)
{
uint8 bdata Status;
do
{// .0=1---reset MODRe,进入复位模式,以便设置相应的寄存器
//防止未进入复位模式,重复写入
SJA_MOD = RM_BIT |AFM_BIT;
Status = SJA_MOD ;
}
while(!(Status & RM_BIT));
SJA_CDR = CANMode_BIT|CLKOff_BIT;// CDR.3=1--时钟关闭, .7=0---basic CAN, .7=1---Peli CAN 时钟分频
SJA_BTR0 = 0x03;
SJA_BTR1 = 0x1c;//16M晶振,波特率125Kbps
SJA_IER = RIE_BIT;// .0=1--接收中断使能; .1=0--关闭发送中断使能
SJA_OCR = NormalMode|Tx0PullDn|OCPOL1_BIT|Tx1PullUp;// 配置输出控制寄存器
SJA_CMR = RRB_BIT;//释放接收缓冲器
SJA_ACR0 = 0x11;
SJA_ACR1 = 0x22;
SJA_ACR2 = 0x33;
SJA_ACR3 = 0x44;//初始化标示码 验收代码寄存器
SJA_AMR0 = 0xff;
SJA_AMR1 = 0xff;
SJA_AMR2 = 0xff;
SJA_AMR3 = 0xff;//初始化掩码 验收屏蔽寄存器
do //确保进入自接收模式
{
SJA_MOD = STM_BIT;
Status = SJA_MOD;
}
while( !(Status & STM_BIT) );
}
//发送数据函数
void Peli_TXD( void )
{
uint8 data Status;
//初始化标示码头信息
TX_buffer[0] = 0x88;//.7=0扩展帧;.6=0数据帧; .3=1数据长度
TX_buffer[1] = 0x01;//本节点地址
TX_buffer[2] = 0x02;//
TX_buffer[3] = 0x03;//
TX_buffer[4] = 0x04;//
//初始化发送数据单元
TX_buffer[5] = Txd_data;
TX_buffer[6] = 0x22;
TX_buffer[7] = 0x33;
TX_buffer[8] = 0x44;//
TX_buffer[9] = 0x55;//
TX_buffer[10] = 0x66;//
TX_buffer[11] = 0x77;//
TX_buffer[12] = 0x88;//
do
{
Status = SJA_SR;
LED_RED = 0;
}
while( Status & RS_BIT); //SR.4=1 正在接收,等待
do
{
Status = SJA_SR;
LED_RED = 0;
}
while(!(Status & TCS_BIT)); //SR.3=0,发送请求未处理完,等待
do
{
Status = SJA_SR;
LED_RED = 0;
}
while(!(Status & TBS_BIT)); //SR.2=0,发送缓冲器被锁。等待
LED_RED = !LED_RED;
LED_GER = !LED_GER;
SJA_TBSR0 = TX_buffer[0];
SJA_TBSR1 = TX_buffer[1];
SJA_TBSR2 = TX_buffer[2];
SJA_TBSR3 = TX_buffer[3];
SJA_TBSR4 = TX_buffer[4];
SJA_TBSR5 = TX_buffer[5];
SJA_TBSR6 = TX_buffer[6];
SJA_TBSR7 = TX_buffer[7];
SJA_TBSR8 = TX_buffer[8];
SJA_TBSR9 = TX_buffer[9];
SJA_TBSR10 = TX_buffer[10];
SJA_TBSR11 = TX_buffer[11];
SJA_TBSR12 = TX_buffer[12];
SJA_CMR = SRR_BIT;//置位自发送接收请求
}
//延时函数
void mDelay(uint16 mtime)
{
for(; mtime > 0; mtime--)
{
uint8 j = 244;
while(--j);
}
}
//数码管显示函数
void LED_Disp_Seg7()
{
LedCtrl = LedCtrl | 0xf0;
DisBuff[0] = Txd_data%10;//取个位数
DisBuff[1] = Txd_data%100/10; //取十位数
DisBuff[2] = Rxd_data%10; //百位数
DisBuff[3] = Rxd_data%100/10; //千位数
LedPort = LED_Disp[DisBuff[0]];
LedCtrl = LedCtrl & 0x7f;
mDelay(5);
LedCtrl = LedCtrl | 0xf0;
LedPort = LED_Disp[DisBuff[1]];
LedCtrl = LedCtrl & 0xbf;
mDelay(5);
LedCtrl = LedCtrl | 0xf0;
LedPort = LED_Disp[DisBuff[2]];
LedCtrl = LedCtrl & 0xdf;
mDelay(5);
LedCtrl = LedCtrl | 0xf0;
LedPort = LED_Disp[DisBuff[3]];
LedCtrl = LedCtrl & 0xef;
mDelay(5);
LedCtrl = LedCtrl | 0xf0;
}
#ifndef __CONFIG_H__
#define __CONFIG_H__
#define Fclk 11059200UL /*使用11.0592M晶体*/
#define BAUD 9600UL /*波特率定义为9600*/
#define uint8 unsigned char
#define uint16 unsigned short int
#define uint32 unsigned long int
#define int8 signed char
#define int16 signed short int
#define int32 signed long int
#define uint64 unsigned long long int
#define int64 signed long long int
#endif
#ifndef __SJAPELICAN_H__
#define __SJAPELICAN_H__
#include <absacc.h>
#include "config.h"
//数码管段码显示:0~f,不亮
uint8 code LED_Disp[] =
{
0xC0,//0
0xF9,//1
0xA4,//2
0xB0,//3
0x99,//4
0x92,//5
0x82,//6
0xF8,//7
0x80,//8
0x90,//9
0x88,//10-a
0x83,//11-b
0xC6,//12-c
0xA1,//13-d
0x86,//14-e
0x8E //15-f
};
//sfr LedPort = 0x80; //段选段P0
//sfr LedCtrl = 0xa0; //位选段P2
#define LedPort P0 //段选段P0 --- 要显示的数字
#define LedCtrl P2 //段选段P2 --- 选择那个数码管
uint8 DisBuff[4];
#define FrameNum 13//一帧字节数
uint8 RX_buffer[FrameNum]; //接收的数据
uint8 TX_buffer[FrameNum]; //接收的数据
uint8 Txd_data = 0;//CAN总线要发送的数据,也是要在数码管1-2位置显示的数据
uint8 Rxd_data = 0;//CAN总线要接收的数据,也是要在数码管3-4位置显示的数据
sbit SJA_RST = P2^3;//SJA1000复位管脚
sbit SJA_CS = P2^0;//SJA1000片选管脚
sbit LED_RED=P1^0;
sbit LED_GER=P1^1;
void MCU_Init(void); //CPU初始化
void Peli_Init(void); // 初始化CAN总线芯片
void Peli_TXD(void);//CAN发送子函数
void mDelay(uint16 mtime);//延时子函数
void LED_Disp_Seg7();//显示子函数
#define SJA_BASE_ADR 0xfe00 //寄存器地址的基址
//SJA1000寄存器地址定义,作用在Peli模式,扩展帧方式
/**********************
模式控制寄存器及其位定义
************************/
#define SJA_MOD XBYTE[SJA_BASE_ADR + 0x00]
#define RM_BIT 0x01 //复位模式请求位
#define LOM_BIT 0x02 //只听模式位
#define STM_BIT 0x04 //自检模式位
#define AFM_BIT 0x08 //验收滤波器模式位
#define SM_BIT 0x10 //睡眠模式位
/**********************
命令寄存器及其位定义
************************/
#define SJA_CMR XBYTE[SJA_BASE_ADR + 0x01]
#define TR_BIT 0x01 //发送请求位
#define AT_BIT 0x02 //中止发送位
#define RRB_BIT 0x04 //释放接收缓冲器位
#define CDO_BIT 0x08 //清除数据溢出位
#define SRR_BIT 0x10 //自身接收请求位
/**********************
状态寄存器及其位定义
************************/
#define SJA_SR XBYTE[SJA_BASE_ADR + 0x02]
#define RBS_BIT 0x01 //接收缓冲器状态位
#define DOS_BIT 0x02 //数据溢出状态位
#define TBS_BIT 0x04 //发送缓冲器状态位
#define TCS_BIT 0x08 //发送完成状态位
#define RS_BIT 0x10 //接收状态位
#define TS_BIT 0x20 //发送状态位
#define ES_BIT 0x40 //错误状态位
#define BS_BIT 0x80 //总线状态位
/**********************
中断寄存器及其位定义
************************/
#define SJA_IR XBYTE[SJA_BASE_ADR + 0x03]
#define RI_BIT 0x01 //接收中断位
#define TI_BIT 0x02 //发送中断位
#define EI_BIT 0x04 //错误警告中断位
#define DOI_BIT 0x08 //数据溢出中断位
#define WUI_BIT 0x10 //唤醒中断位
#define EPI_BIT 0x20 //错误消极中断位
#define ALI_BIT 0x40 //仲裁丢失中断位
#define BEI_BIT 0x80 //总线错误中断位
/**********************
中断使能寄存器及其位定义
************************/
#define SJA_IER XBYTE[SJA_BASE_ADR + 0x04]
#define RIE_BIT 0x01 //接收中断使能位
#define TIE_BIT 0x02 //发送中断使能位
#define EIE_BIT 0x04 //错误警告中断使能位
#define DOIE_BIT 0x08 //数据溢出中断使能位
#define WUIE_BIT 0x10 //唤醒中断使能位
#define EPIE_BIT 0x20 //错误消极中断使能位
#define ALIE_BIT 0x40 //仲裁丢失中断使能位
#define BEIE_BIT 0x80 //总线错误中断使能位
#define SJA_BTR0 XBYTE[SJA_BASE_ADR + 0x06] //总线定时器0寄存器
#define SJA_BTR1 XBYTE[SJA_BASE_ADR + 0x07] //总线定时器1寄存器
#define SAM_BIT 0x80 //采样模式位;0==总线被采样1次;1== 总线被采样3次
/**********************
输出控制寄存器及其位定义
************************/
#define SJA_OCR XBYTE[SJA_BASE_ADR + 0x08]
/*OCMODE1 ,OCMODE0 */
#define BiPhaseMode 0x00 //双相输出模式
#define NormalMode 0x02 //正常输出模式
#define ClkOutMode (0x01|0x02) //时钟输出模式
/*TX1 的输出管脚配置*/
#define OCPOL1_BIT 0x20 //输出极性控制位
#define Tx1Float 0x00 //配置为悬空
#define Tx1PullDn 0x40

博主在SJA1000+STC89C52硬件电路上进行自收发开发,原计划用开发板和TJA1050模块实现,未成功后改用CAN开发板。期间参考吴坚鸿大神源码,修改程序后出现显示问题,发的数字和收的数字差值改变,博主对此现象原因存疑。
5602

被折叠的 条评论
为什么被折叠?



