The project needs to use the CAN controller SJA1000 chip, and the main control chip used is ARM9, but no matter how I debug on ARM9, it doesn't work. As a last resort, I have to test whether the 51 series microcontroller can work with this chip. I need to rule out the chip problem, but I find that when you don't know much about a new chip, it takes a lot of effort to operate it without any experience. So I recorded the process in detail for review. The key is to read the chip data sheet carefully.
The chips and data used are listed in detail as follows:
1. Main control chip (STC89C52RC), CAN controller (SJA1000T), CAN transceiver (PCA82C250), PCA82C251 seems to be better
2. Download the corresponding chip manual and SJA1000 Independent CAN Controller Application Guide.pdf.
Partial circuit diagram:
What needs attention is the reset unit design. It is best to use software reset. I chose P2.6 reset. In addition, the /INT port of SJA1000T needs to add a pull-up resistor, otherwise it will be always low. In addition, XTAL1 and CLKOUT are not connected. The frequency of STC89C52 is provided by an independent 11.592MHZ crystal oscillator. There seems to be nothing else to pay special attention to. Just connect correctly according to the circuit diagram. The next step is to write the test code.
The process mainly refers to the application guide, and the main steps are as follows:
Set the serial port working mode, 8n1
Set to use timer 1
Set working mode 2 and baud rate
Start timer 1 and set receive interrupt
Set external interrupt priority and interrupt mode (falling edge interrupt gate)
Enable global and external interrupts
Reset the SJA1000 chip and give a negative pulse to the RST pin. After reset, the default is to enter the reset mode, but it is better to confirm that the chip enters the reset mode and then output a prompt message.
Set the clock distribution register, mainly to set the PeliCAN mode, receive RX0 or RX1 interrupt
Set the CLKOUT output, set the acceptance code register and the acceptance mask register, and combine these two to filter the data packet to determine whether it needs to be received by this node
Configure the bus timer register, set the transmission frequency and output mode, confirm to enter the self-receiving mode, and send data
Use a while loop to wait for the interrupt to arrive, compile and download to the STC89C52 chip, the test results are shown in the figure below:
Design source code:
/*------------------------------------------------ ----------------------------------
HELLO.C
Copyright 1995-2005 Keil Software, Inc.
-------------------------------------------------- ----------------------------*/
#include
/* for the intended 8051 derivative */
#include
#include "sja1000_reg.h" /* sja1000T register definition file */
#include
sbit SJARst = P2 ^ 6; // reset control
/*------------------------------------------------
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 MONITOR51
SCON = 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 */
#endif
PX0=1; //External interrupt 0 high priority
IT0=1; //Set INT0 to falling edge interrupt
EX0=1; //Enable INT0 interrupt
/*------------------------------------------------
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(); //mainly reset the chip
/*
Enter the reset Mode
*/
REG_MODE = 0x01;
while((REG_MODE&0x01)!= 0x01); //Confirm to enter reset mode
printf("1.Enter the Reset Mode,REG_MODE=0x%.4x\n",REG_MODE);
REG_CDR = 0xc8; //Set the clock divider register. CDR.7 = 1, PeliCAN mode; CDR.6 (RX0 activated, RX1 closed) fCLKOUT = fOSC/2, CDR.3 (Close the CLKOUT)
REG_RBSA = 0x00; //RX buffer start address
/*Configure acceptance code and mask register*/
REG_ACR0 = 0xff; //Acceptance code register
REG_ACR1 = 0xff;
REG_ACR2 = 0xff;
REG_ACR3 = 0xff;
REG_AMR0 = 0xff; //Acceptance mask register, receive data packets with any identifier
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 mode interrupt enable, receive interrupt enable, transmit interrupt disable
REG_OCR = 0x1a; //Set output mode: normal output, output from TX0 port; TX1 is left floating
REG_MODE = 0x0c; //Enter self-receiving mode. CDR.3 (select single acceptance filter), CDR.2 (this mode can detect all nodes)
while(REG_MODE != 0x0c); //Confirm to enter self-receiving mode
printf("2.Enter the self-test Mode\n",REG_MODE);
SJA1000_TxData(); //Send data
printf("\n\n");
//SJA1000_Rx_Display(); //Receive data display
EA = 1; // Enable global interrupt
while(1);
}
void SJA1000_TxData(void)
{
while(REG_SR & 0x10); //Execution can continue only when SJA1000 is not in receiving state, SR.4==0x1, receiving, waiting
while(!(REG_SR & 0x08)); //SR.3=0, the sending request is not processed, wait until SR.3=1
while(!(REG_SR & 0x04)); //SR.2=0, the transmit buffer is locked. Wait until SR.2=1
REG_TxBuffer0 = 0x08; //Frame information, standard frame, data frame, 8 bytes
REG_TxBuffer1 = 0xFF; //Identifier 1
REG_TxBuffer2 = 0xFF; //Identifier 2
REG_TxBuffer3 = 0x11; //Send data bit: 1
REG_TxBuffer4 = 0x22; //Send data bit: 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; //Self-receive
while(!(REG_SR & 0x08));//Detection sent completed
}
/****************************************************** ***********
Function: ex0_int
Description: Interrupt service routine
Entrance: No
Returns: None
*************************************************** *********/
void handle_int(void) interrupt 0 using 1
{
if(REG_IR & 0x01) //Receive interrupt occurs
{
#pragma disable
printf( "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);
}/*Display the sent information. Previously, the send buffer was used directly. This method is wrong because the 13 registers starting from 0x10 are the receive buffer when reading and the send buffer when writing*/
void SJA_Init(void)
{
//SJA1000 reset
unsigned char i;
for(i = 0;i < 125;i++);
SJARst = 0;
for(i = 0;i < 125;i++); // Give the RST pin a low pulse
SJARst = 1;
for(i = 0;i < 125;i++);
}
sja1000_reg.h defines:
/*
SJA1000 register related control
*/
#ifndef SJA1000_H
#define SJA1000_H
/*Specify the starting address of SJA1000 as 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 reserved
#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 reserved
#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]
/*Receive buffer*/
#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]
/*Send buffer*/
#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]
Previous article:Implementation of CAN communication based on 51 single chip microcomputer SJA1000
Next article:12864 Liquid Crystal Display Principle (C Program)
Recommended ReadingLatest update time:2024-11-16 14:29
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- How to enable TI 15.4-Stack to support 470M frequency band
- EEWORLD University - SimpleLink Wi-Fi CC3120 Project Introduction
- OC5501-OC5502-LED automotive high and low beam solutions (no diode design, applied to automotive lights, MR16, architectural lighting)
- I would like to ask you guys, do I need to draw PCB in electronic competitions?
- stm32f407 driver enc28j60
- LM3478 step-down problem
- Does anyone understand the PD power supply protocol? USB Type-C PD power supply problem!
- C2000 MCU implements grid-connected micro solar inverter
- EEWORLD University Hall----Microcomputer Principles and System Design
- EEWORLD University Hall----RF Amplifier Design Tian Qingcheng, Chinese University, Taiwan