STC89C52+SJA1000 self-transmitting and receiving program record

Publisher:雅意盎然Latest update time:2018-09-09 Source: eefocusKeywords:STC89C52 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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:


  1. Set the serial port working mode, 8n1

  2. Set to use timer 1

  3. Set working mode 2 and baud rate

  4. Start timer 1 and set receive interrupt

  5. Set external interrupt priority and interrupt mode (falling edge interrupt gate)

  6. Enable global and external interrupts

  7. 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.

  8. Set the clock distribution register, mainly to set the PeliCAN mode, receive RX0 or RX1 interrupt

  9. 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

  10. Configure the bus timer register, set the transmission frequency and output mode, confirm to enter the self-receiving mode, and send data

  11. 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 /* special function register declarations */

                                  /* for the intended 8051 derivative */

 

#include /* prototype declarations for I/O functions */

#include "sja1000_reg.h" /* sja1000T register definition file */

#include /* Mainly used to address external memory */

 

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]  


Keywords:STC89C52 Reference address:STC89C52+SJA1000 self-transmitting and receiving program record

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

Light up the LED
A previous article introduced the principle of LED luminescence. We only need to set the STC89C52 pin level corresponding to the light-emitting diode to a low level. OK, let's light up D1 D3 D5. How do you know which pin controls which LED? I think the circuit principle information provided will explain t
[Microcontroller]
Light up the LED
Matrix keyboard of single chip microcomputer
The following is a matrix keyboard program for stc89c52 MCU. The keyboard is connected to port P0 and displayed on port P2. #include reg52.h #define uchar unsigned char #define uint unsigned int sbit key1=P3^2; sbit key2=P3^3; uchar code tab ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号