项目中需要使用到CAN控制器SJA1000芯片,使用的主控芯片是ARM9,但是在ARM9上怎么调试也不通,不得已,只好先测试下51系列的单片机上是否可以和此芯片协同工作,需要排除芯片的问题,但是发现当你不太了解一个新芯片的时候,若要操作该芯片,而你又没啥经验,是需要费很大的功夫的。所以把过程详细的记录下来,以备复习。关键还是得仔细看芯片数据手册。

使用到的芯片和资料详细列出如下:

1.      主控芯片(STC89C52RC),CAN控制器(SJA1000T),CAN收发器(PCA82C250)似乎PCA82C251更好些

2.      下载对应的芯片手册,以及SJA1000独立的CAN控制器应用指南.pdf。

部分电路图:

其中需要注意的是复位单元设计,最好使用软件复位,我选择的是P2.6复位,另外SJA1000T的/INT端口需要添加上拉电阻,不然会恒为低。另外XTAL1和CLKOUT不连接,STC89C52由独立的11.592MHZ晶振提供频率,其他好像没啥需要特别注意的,只要按照电路图正确连接即可。下来就是编写测试代码。

过程主要参考应用指南,主要步骤如下:

  1. 设置串口工作模式,8n1
  2. 设置使用定时器1
  3. 设置工作方式2和波特率
  4. 启动定时器1,设置接收中断
  5. 设置外部中断优先级和中断方式(下降沿中断门)
  6. 使能全局和外部中断
  7. 复位SJA1000芯片,给引脚RST一个负脉冲。复位后默认是进入复位模式,但是最好还是确认芯片进入复位模式,然后输出提示信息,
  8. 设置时钟分配寄存器,主要是设置PeliCAN模式,接收RX0还是RX1中断
  9. 设置CLKOUT输出,设置验收码寄存器和验收屏蔽寄存器,这两个结合起来来过滤数据包,判断是否需要被本节点接收
  10. 配置总线定时器寄存器,设置发送频率和输出模式,确认进入自接收模式,发送数据
  11. 使用while循环等待中断到来,编译并下载到STC89C52芯片上,测试结果如下图所示:

设计源码:

/*------------------------------------------------------------------------------
HELLO.CCopyright 1995-2005 Keil Software, Inc.
------------------------------------------------------------------------------*/#include <REG52.H>                /* special function register declarations   *//* for the intended 8051 derivative         */#include <stdio.h>                /* prototype declarations for I/O functions */
#include "sja1000_reg.h"          /* sja1000T的寄存器定义文件*/
#include <absacc.h>                 /* 主要是用于寻址外部存储器*/sbit SJARst = P2 ^ 6; //复位控制                                     /*------------------------------------------------
The main C function.  Program execution starts
here after stack initialization.
------------------------------------------------*/
void main (void) {/*------------------------------------------------
Setup the serial port for 9600 baud at 11.0592MHz.
------------------------------------------------*/
#ifndef MONITOR51SCON  = 0x50;              /* SCON: mode 1, 8-bit UART, enable rcvr      */TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */TH1   = 0xFD;                /* TH1:  reload value for 9600 baud @ 11.0595MHZ   */TR1   = 1;                  /* TR1:  timer 1 run                          */TI    = 1;                  /* TI:   set TI to send first char of UART    */
#endifPX0=1;                                          //外部中断0高优先级IT0=1;                                          //设置INT0为下降沿中断EX0=1;                                          //使能INT0中断/*------------------------------------------------
Note that an embedded program never exits (because
there is no operating system to return to).  It
must loop and execute forever.
------------------------------------------------*/printf ("Hello World\n");   /* Print "Hello World" */SJA_Init();//主要是使芯片复位/*Enter the reset Mode*/REG_MODE = 0x01; while((REG_MODE&0x01)!= 0x01); //确定进入复位模式 printf("1.Enter the Reset Mode,REG_MODE=0x%.4x\n",REG_MODE);REG_CDR = 0xc8;//设置时钟分频寄存器。CDR.7 = 1,PeliCAN模式;CDR.6(RX0激活,关闭RX1)  fCLKOUT = fOSC/2, CDR.3(Close the CLKOUT)REG_RBSA = 0x00;//RX缓冲器起始地址    /*Configure acceptance code and mask register*/                                                    REG_ACR0 = 0xff;//验收码寄存器                       REG_ACR1 = 0xff;                            REG_ACR2 = 0xff;                            REG_ACR3 = 0xff;                            REG_AMR0 = 0xff;//验收屏蔽寄存器,接收任何标识符的数据包         REG_AMR1 = 0xff;                            REG_AMR2 = 0xff;                            REG_AMR3 = 0xff;    /*configure bus timing registers*/REG_BTR0 = 0x00;                            REG_BTR1 = 0x14; //100k     REG_IR_ABLE = 0x01;//Peli模式中断使能,接收中断使能,发送中断禁止                  REG_OCR = 0x1a;//设置输出模式:正常输出,从TX0口输出;TX1悬空REG_MODE = 0x0c; //进入自接收模式.CDR.3(选择单个验收滤波器),CDR.2 (此模式可以检测所有节点)while(REG_MODE != 0x0c);//确定进入自接收模式下printf("2.Enter the self-test Mode\n",REG_MODE);SJA1000_TxData();//发送数据printf("\n\n");//SJA1000_Rx_Display();//接收数据展示EA = 1;//使能全局中断while(1);
}void SJA1000_TxData(void)
{while(REG_SR & 0x10);//当SJA1000不处于接收状态时才可继续执行,SR.4==0x1,正在接收,等待while(!(REG_SR & 0x08)); //SR.3=0,发送请求未处理完,等待直到SR.3=1while(!(REG_SR & 0x04)); //SR.2=0,发送缓冲器被锁。等待直到SR.2=1   REG_TxBuffer0 = 0x08;//帧信息,标准帧,数据帧,8字节        REG_TxBuffer1 = 0xFF;//标识符1                             REG_TxBuffer2 = 0xFF;//标识符2                     REG_TxBuffer3 = 0x11;//发送数据位:1                       REG_TxBuffer4 = 0x22;//发送数据位:2                       REG_TxBuffer5 = 0x33;                                      REG_TxBuffer6 = 0x44;                                      REG_TxBuffer7 = 0x55;                                      REG_TxBuffer8 = 0x66;                                      REG_TxBuffer9 = 0x77;                                      REG_TxBuffer10 = 0x88;//here Over                          SJA1000_Tx_Display();REG_CMD = 0x10;//自接收while(!(REG_SR & 0x08));//检测发送完毕
}
/************************************************************函数:ex0_int 说明:中断服务程序入口:无返回:无***********************************************************/
void handle_int(void) interrupt 0 using 1
{if(REG_IR & 0x01)      //产生了接收中断{ #pragma disableprintf( " Received message.\n");printf( " RBSR3 = %x \n", REG_RxBuffer3 );printf( " RBSR4 = %x \n", REG_RxBuffer4 );printf( " RBSR5 = %x \n", REG_RxBuffer5 );     printf( " RBSR6 = %x \n", REG_RxBuffer6 );     printf( " RBSR7 = %x \n", REG_RxBuffer7 );     printf( " RBSR8 = %x \n", REG_RxBuffer8 );     printf( " RBSR9 = %x \n", REG_RxBuffer9 );     printf( " RBSR10 = %x \n",REG_RxBuffer10);   }
}
void SJA1000_Tx_Display(void)
{printf( " TBSR3 = 0x%.4x \n", REG_TxBufferRd3 );  printf( " TBSR4 = 0x%.4x \n", REG_TxBufferRd4 );  printf( " TBSR5 = 0x%.4x \n", REG_TxBufferRd5 );  printf( " TBSR6 = 0x%.4x \n", REG_TxBufferRd6 );  printf( " TBSR7 = 0x%.4x \n", REG_TxBufferRd7 );  printf( " TBSR8 = 0x%.4x \n", REG_TxBufferRd8 );  printf( " TBSR9 = 0x%.4x \n", REG_TxBufferRd9 );  printf( " TBSR10 = 0x%.4x \n",REG_TxBufferRd10);
}/*显示发送的信息,之前直接使用发送缓冲区,这种方法是错误的,因为0x10开始的13个寄存器,读的时候是接收缓冲区,写的时候是发送缓冲区*/void SJA_Init(void)
{    //SJA1000复位                                        unsigned char i;                            for(i = 0;i < 125;i++);           SJARst = 0;                                 for(i = 0;i < 125;i++);//给RST引脚一个低脉冲SJARst = 1;                                 for(i = 0;i < 125;i++);
}                          

sja1000_reg.h定义:

/*SJA1000的寄存器有关控制*/
#ifndef SJA1000_H
#define SJA1000_H
/*指定SJA1000的起始地址为0x7800*/
#define SJA_REG_BaseADD 0x7800  #define REG_MODE XBYTE[SJA_REG_BaseADD + 0x00]
#define REG_CMD XBYTE[SJA_REG_BaseADD + 0x01]
#define REG_SR XBYTE[SJA_REG_BaseADD + 0x02]
#define REG_IR XBYTE[SJA_REG_BaseADD + 0x03]
#define REG_IR_ABLE XBYTE[SJA_REG_BaseADD + 0x04]
#define REG_BTR0 XBYTE[SJA_REG_BaseADD + 0x06] //05保留
#define REG_BTR1 XBYTE[SJA_REG_BaseADD + 0x07]
#define REG_OCR XBYTE[SJA_REG_BaseADD + 0x08]
#define REG_TEST XBYTE[SJA_REG_BaseADD + 0x09]
#define REG_ALC XBYTE[SJA_REG_BaseADD + 0x0b] //0a保留
#define REG_ECC XBYTE[SJA_REG_BaseADD + 0x0c]
#define REG_EMLR XBYTE[SJA_REG_BaseADD + 0x0d]
#define REG_RXERR XBYTE[SJA_REG_BaseADD + 0x0e]
#define REG_TXERR XBYTE[SJA_REG_BaseADD + 0x0f]                      #define REG_ACR0 XBYTE[SJA_REG_BaseADD + 0x10]
#define REG_ACR1 XBYTE[SJA_REG_BaseADD + 0x11]
#define REG_ACR2 XBYTE[SJA_REG_BaseADD + 0x12]
#define REG_ACR3 XBYTE[SJA_REG_BaseADD + 0x13]
#define REG_AMR0 XBYTE[SJA_REG_BaseADD + 0x14]
#define REG_AMR1 XBYTE[SJA_REG_BaseADD + 0x15]
#define REG_AMR2 XBYTE[SJA_REG_BaseADD + 0x16]
#define REG_AMR3 XBYTE[SJA_REG_BaseADD + 0x17]                       /*接收缓冲区*/
#define REG_RxBuffer0 XBYTE[SJA_REG_BaseADD + 0x10]
#define REG_RxBuffer1 XBYTE[SJA_REG_BaseADD + 0x11]
#define REG_RxBuffer2 XBYTE[SJA_REG_BaseADD + 0x12]
#define REG_RxBuffer3 XBYTE[SJA_REG_BaseADD + 0x13]
#define REG_RxBuffer4 XBYTE[SJA_REG_BaseADD + 0x14]
#define REG_RxBuffer5 XBYTE[SJA_REG_BaseADD + 0x15]
#define REG_RxBuffer6 XBYTE[SJA_REG_BaseADD + 0x16]
#define REG_RxBuffer7 XBYTE[SJA_REG_BaseADD + 0x17]
#define REG_RxBuffer8 XBYTE[SJA_REG_BaseADD + 0x18]
#define REG_RxBuffer9 XBYTE[SJA_REG_BaseADD + 0x19]
#define REG_RxBuffer10 XBYTE[SJA_REG_BaseADD + 0x1a]
#define REG_RxBuffer11 XBYTE[SJA_REG_BaseADD + 0x1b]
#define REG_RxBuffer12 XBYTE[SJA_REG_BaseADD + 0x1c]  /*发送缓冲区*/
#define REG_TxBuffer0 XBYTE[SJA_REG_BaseADD + 0x10]
#define REG_TxBuffer1 XBYTE[SJA_REG_BaseADD + 0x11]
#define REG_TxBuffer2 XBYTE[SJA_REG_BaseADD + 0x12]
#define REG_TxBuffer3 XBYTE[SJA_REG_BaseADD + 0x13]
#define REG_TxBuffer4 XBYTE[SJA_REG_BaseADD + 0x14]
#define REG_TxBuffer5 XBYTE[SJA_REG_BaseADD + 0x15]
#define REG_TxBuffer6 XBYTE[SJA_REG_BaseADD + 0x16]
#define REG_TxBuffer7 XBYTE[SJA_REG_BaseADD + 0x17]
#define REG_TxBuffer8 XBYTE[SJA_REG_BaseADD + 0x18]
#define REG_TxBuffer9 XBYTE[SJA_REG_BaseADD + 0x19]
#define REG_TxBuffer10 XBYTE[SJA_REG_BaseADD + 0x1a]
#define REG_TxBuffer11 XBYTE[SJA_REG_BaseADD + 0x1b]
#define REG_TxBuffer12 XBYTE[SJA_REG_BaseADD + 0x1c]
#define REG_TxBufferRd0 XBYTE[SJA_REG_BaseADD + 0x60]
#define REG_TxBufferRd1 XBYTE[SJA_REG_BaseADD + 0x61]
#define REG_TxBufferRd2 XBYTE[SJA_REG_BaseADD + 0x62]
#define REG_TxBufferRd3 XBYTE[SJA_REG_BaseADD + 0x63]
#define REG_TxBufferRd4 XBYTE[SJA_REG_BaseADD + 0x64]
#define REG_TxBufferRd5 XBYTE[SJA_REG_BaseADD + 0x65]
#define REG_TxBufferRd6 XBYTE[SJA_REG_BaseADD + 0x66]
#define REG_TxBufferRd7 XBYTE[SJA_REG_BaseADD + 0x67]
#define REG_TxBufferRd8 XBYTE[SJA_REG_BaseADD + 0x68]
#define REG_TxBufferRd9 XBYTE[SJA_REG_BaseADD + 0x69]
#define REG_TxBufferRd10 XBYTE[SJA_REG_BaseADD + 0x6a]
#define REG_TxBufferRd11 XBYTE[SJA_REG_BaseADD + 0x6b]
#define REG_TxBufferRd12 XBYTE[SJA_REG_BaseADD + 0x6c]

STC89C52+SJA1000自收发程序记录相关推荐

  1. php留言板记录ip,如何用php程序记录来访IP

    如何用php程序记录来访IP 关注:226  答案:4  手机版 解决时间 2021-02-16 00:05 提问者失夜久伴你 2021-02-15 01:22 如何用php程序获取来访IP,然后保存 ...

  2. Android NFC 应用程序记录ARR

    android应用程序记录 1.在Android4.0中引入应用程序记录(AAR),当扫描到写入AAR的NFC标签时,启动相应的应用程序. 2.AAR有嵌入到NdefRecord内部的应用程序包名.A ...

  3. 五子棋游戏程序记录和复盘功能设置

    五子棋游戏程序记录和复盘功能设置 大家都玩过手机的小游戏吧.我是编程爱好者,喜欢动脑筋研究一些算法,编程做出小游戏程序,很有趣很有成就感.在学习VB6编程时就编制过钻石棋和伤脑筋十二块那样的游戏,都是 ...

  4. 微信小程序记录用户行为浏览记录和停留时间以及小程序全局分享

    微信小程序记录用户行为浏览记录和停留时间以及小程序全局分享 项目需求 1.后台统计一个用户在我们小程序的每个页面的停留时间 2,前台用户可以在个人中心看到自己的分享记录以及多少人查看 需求分析 需求一 ...

  5. S32DS使用Jlink下载S32K144程序记录

    一,S32DS配置. 参考文章 在S32DS中使用J-Link调试S32K144开发板_大橙员的博客-CSDN博客 新建工程 以自带例程"S32K144_Project_ADC"为 ...

  6. 智能温室管理系统 2 树莓派lora收发程序python、NBiot发送数据到华为云平台

    第二部分是树莓派的部分 用的python3写的 功能 一 实现lora收发消息 通过spi口实现 二 收发NBIOT的数据 通过串口实现,注意树莓派的串口开始是不能用的,需要配置,当时我这个渣渣配了一 ...

  7. 时钟电路程序设计c语言,STC89C52单片机简易时钟程序电路设计(附源代码和电路图)...

    51(STC89C52)单片机简易时钟程序电路设计(附源代码和电路图) 上一篇做了一个温湿度采集电路,觉得这东西玩起来还是挺有意思,然后就想做一个时钟,于是就有了下文 1.成品图 51hei图片_20 ...

  8. 小程序记录页面停留时间

    小程序记录页面停留时间 小程序记录页面停留时间的传统做法,每个页面的onshow开始计时,onhide和onUnload停止计时,但每个需要加载的页面都要调用一遍方法,比较麻烦,现可以在app.js ...

  9. 超市购物打印小票的简单程序 记录下来

    做了2个版本的超市购物小票打印程序,做过记录 一.C/S样图如下:      其中 输入商品的编码 回车 将会调用该商品的信息,显示在下面的DataGridView中 ,DataGridView中数量 ...

最新文章

  1. cpp cu入门教程
  2. SpringBoot下的工作流Activiti开发
  3. CentOS6.5最小化安装+自定义安装包
  4. Gartner: 2016年十大安全预测
  5. 洛谷 P1886 滑动窗口
  6. 查询DB中每个表占用的空间大小
  7. python集合操作班级干部竞选演讲稿_精选竞选班干部的演讲稿集合7篇
  8. java中的foreach用法及总结
  9. python编程(反汇编)
  10. 详解解决CAS机制中ABA问题的AtomicStampedReference
  11. 冰点下载器手机版apk_冰点文库下载器app下载_冰点文库下载器手机安卓版软件下载v1.0.3...
  12. 设计模式之责任链模式(Java实现)
  13. 北师大1903计算机在线答案,[南开大学(本部)]20秋学期(1709、1803、1809、1903、1909、2003、2009 )《程序设计基础(下)》在线作业-2...
  14. python在cmd中打印彩色文字
  15. qq邮箱的SMTP服务器是什么
  16. IDEA解决开两个窗口问题
  17. 0行代码拿210万年薪,ChatGPT催生新型「程序员」岗:工作纯靠和AI聊天
  18. 显示单月的日历c语言编程,显示单月的日历的C程序
  19. big_screen,一款超强大的Python 可视化大屏!
  20. R语言GO富集分析报错求助

热门文章

  1. ubuntu下U盘刻录工具,用来刻录windows系统
  2. axb-2019-fmt64
  3. 《博哥玩Arduino》- 蓝牙七彩灯优化版V1.0
  4. 新闻丨智链万源CEO董宁参加可信区块链推进计划第二次全体会议
  5. 知微传感Dkam系列3D相机PCL应用篇:PCL读入3D相机数据
  6. php理财逻辑流程,理财小白成长记之底层逻辑
  7. 应届生简历应该如何排版才能更吸引HR?
  8. [记录] 文献管理 —— 将自己在Mendeley上的几千篇文献进行归档 (踩过的坑)
  9. 京东商城:已经没有上市机会
  10. 那些简历造假拿到 Offer 的人,后来怎么样了?