admin管理员组

文章数量:1404773

I’m encountering some issues with the CAN BUS module on the PIC18F2580. I should probably mention that I’m new to working with CAN, so I may have overlooked something quite simple.

Currently, I’m attempting to send a single CAN message at 250kbps (using ID 0x202 with 8 bytes).

For now, I’ve set the first byte to 0xFF just for testing purposes (I plan to modify it based on an ADC reading later). I'm not interested in receiving messages, so I don't need any specific interrupts and set RX pin.

At the moment, I’m seeing 0V on the CANTX pin (RB2) to the transceiver.
Investigating the problem and debugging with a LED, I noticed that

TXB0CONbits.TXREQ

is never going back to 0 after the fisrt transmit, thus never actually transmitting.

I’m using MPLABX v6.00 and XC8 V3.00.

May I ask if any CAN-PIC expert could explain what is the issue? It wuold be greatly appreciated. Thanks!

Code:

#pragma config [...various...] //ask if you need to see them
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
 
#define _XTAL_FREQ 1000000  // INT OSC frequency
 
// Initialize the ADC module for AN10 (RB0)
void ADC_Init() {
    ADCON1 = 0b00000100;  // Configure AN10 as an analog input
    ADCON2 = 0b10001101;  // Right justification, Fosc/16
    ADCON0 = 0b00101001;  // Select channel AN10
}
 
// Read the ADC value
unsigned int ADC_Read() {
    ADCON0bits.GO = 1;
    while (ADCON0bits.GO);
    return ((unsigned int)(ADRESH << 8) + ADRESL);
}
 
// Initialize the CAN module
void CAN_Init() {
    // Configure CAN pins
    TRISBbits.TRISB2 = 0; // Set CANTX as output
    TRISBbits.TRISB3 = 1; // Set CANRX as input
 
    // Set the CAN module to configuration mode
    CANCON = 0x80; // Configuration mode
    while ((CANSTAT & 0xE0) != 0x80); // Wait until it enters configuration mode
 
    // Set the CAN bus speed (250kbps with Fosc = 1MHz, prescaler Fosc/16)
    BRGCON1 = 0x00; // Prescaler (BRP = 0)
    BRGCON2 = 0xB8; // Propagation segment
    BRGCON3 = 0x05; // Phase segment
 
    // Set the transmission buffer to high priority
    TXB0CON = 0x00;
 
    // Set the CAN module to normal mode
    CANCON = 0x00;
    while ((CANSTAT & 0xE0) != 0x00); // Wait until it enters normal mode
}
 
// Transmit a CAN message
void CAN_Transmit(unsigned int ID, unsigned char *message, unsigned char length) {
    unsigned int timeout = 5000;
 
    // Wait for the buffer to be free
    while (TXB0CONbits.TXREQ && timeout--) {
        __delay_us(10);
    }
    if (timeout == 0) return; // Timeout, exit
 
    // Set the message ID
    TXB0SIDH = (unsigned char)(ID >> 3);  // Upper 8 bits
    TXB0SIDL = (unsigned char)(ID << 5);  // Lower 3 bits + standard frame
 
    // Set the message length
    TXB0DLC = length & 0x0F;
 
    // Copy the data into buffer
    TXB0D0 = message[0];
    TXB0D1 = message[1];
    TXB0D2 = message[2];
    TXB0D3 = message[3];
    TXB0D4 = message[4];
    TXB0D5 = message[5];
    TXB0D6 = message[6];
    TXB0D7 = message[7];
 
    // Enable transmission
    TXB0CONbits.TXREQ = 1;
}
 
int main() {
    unsigned int adc_value;
    unsigned char message[8] = {0xFF};
 
    TRISC = 0x00; // Configure PORTC as output
    ADC_Init();
    CAN_Init();
 
    while (1) {
        adc_value = ADC_Read();
        adc_value = (adc_value * 0x64) / 1023;
        
        /* --------------FUTURE USE-----------------
        //message[0] = (unsigned char)adc_value;
        //message[4] = (adc_value < 0x14) ? 0x00 : 0x01;*/
        
        CAN_Transmit(0x202, message, 8);
        PORTCbits.RC3 ^= 1;
        
        __delay_ms(100);
    }
    return (EXIT_SUCCESS);
}

本文标签: cSimple CAN message with PIC18F2580Stack Overflow