Skocz do zawartości

Pomocna odpowiedź

  • 3 miesiące później...
(edytowany)
1 godzinę temu, PiotrekEl napisał:

Jakbyś wiedział gdzie są dostępne, daj znać. Kupię cały karton😆

Osobiście mam jeszcze ze 20 sztuk 😛 Do tego też płytki (chyba, dawno nie grzebałem tak głęboko w szufladzie) 😉 

Konkretniej ten model: https://pl.mouser.com/ProductDetail/863-NCV7329D10R2G😉 

Edytowano przez H1M4W4R1
  • 2 lat(a) później...
5 godzin temu, arow napisał:

Cześć.

Czy mógłbyś pokazać przykład w ino, który obsługuje tą płytkę z Arduino?

Nie, pisałem w czystym C++ pod RPi Pico.

CPP:

#include <cstdio>
#include "lin.h"

#define LIN_BREAK_WIDTH 14
#define LIN_SYNC 0x55

uint baud;
uint txPin;
uint rxPin;

uint8_t lin_sync = LIN_SYNC;
uart_inst_t* uart;
bool freeHeader = false;
alarm_id_t alarmId;

uint64_t get_lin_time(){
    double micros_d = (double) 1000000 / baud;
    uint64_t micros = (uint64_t) micros_d;

    return micros;
}

void lin_initialize(uart_inst_t *uartInst, uint tx, uint rx, uint baudRate) {
    // Initialize GPIO
    gpio_init(tx);
    gpio_init(rx);
    gpio_set_dir(tx, true);
    gpio_set_dir(rx, false);
    gpio_pull_up(tx);
    gpio_pull_up(rx);
    gpio_put(tx, true);

    // As UART
    gpio_set_function(tx, GPIO_FUNC_UART);
    gpio_set_function(rx, GPIO_FUNC_SIO);

    // Set PIN values
    txPin = tx;
    rxPin = rx;

    // Store BAUD value
    baud = baudRate;

    // Init UART
    uart_init(uartInst, baudRate);
    uart_set_format(uartInst, 8, 1, UART_PARITY_NONE);

    uart = uartInst;
    // READY
}

uint8_t calculate_checksum(uint8_t id, uint8_t* data, uint8_t len, bool enhanced_checksum){
    uint16_t sum = 0;
    for(int q = 0; q < len; q++){
        sum += data[q];
    }

    // IF LIN2, then also consider ID
    if(enhanced_checksum) {
        sum += id;
    }

    // Subtract sum
    while(sum >= 256)
        sum -= 255;

    // Invert sum
    uint8_t sum8 = (uint8_t) sum;
    return ~sum8;
}

bool get_bit(uint8_t input, uint8_t n){
    return (input >> n) & 1;
}

uint8_t set_bit(uint8_t input, uint8_t n, bool value){
    if(value)
        input |= 1 << n;
    else
        input &= ~(1 << n);

    return input;
}

uint8_t lin_get_data_size(uint8_t pid){
    // Reset parity bits
    uint8_t id = set_bit(pid, 7, 0);
    id = set_bit(id, 6, 0);

    if(id <= 0x1F) return 2;
    if(id <= 0x2F) return 4;
    if(id <= 0x3F) return 8;

    return 0;
}

uint8_t lin_calculate_parity(uint8_t id){
    bool p0 = get_bit(id, 0) xor get_bit(id, 1) xor get_bit(id, 2) xor get_bit(id, 4);
    bool p1 = not (get_bit(id, 1) xor get_bit(id, 3) xor get_bit(id, 4) xor get_bit(id, 5));

    id = set_bit(id, 6, p0);
    id = set_bit(id, 7, p1);

    return id;
}


void lin_send_frame(lin_frame* frame)
{
    // Calculate settings
    uint64_t lin_delay = get_lin_time();
    uint8_t id = lin_calculate_parity(frame->id);

    // Break
    gpio_set_function(txPin, GPIO_FUNC_SIO);
    gpio_put(txPin, false); // Send 0 for 14 TLIN
    sleep_us(LIN_BREAK_WIDTH * lin_delay);

    gpio_put(txPin, true);
    sleep_us(lin_delay);

    uint8_t checksum = calculate_checksum(id, frame->data, frame->length, frame->enhanced_checksum);

    gpio_set_function(txPin, GPIO_FUNC_UART);

    // Prepare data array
    uint8_t data[12];
    data[0] = lin_sync;
    data[1] = id;
    for(int q = 2; q < 2 + frame->length; q++){
        data[q] = frame->data[q - 2];
    }
    data[2 + frame->length] = checksum;

    // Send
    uart_write_blocking(uart, data, frame->length + 3);
}

int64_t lin_not_received(alarm_id_t id, void *user_data)
{
    if(alarmId == id) {
        // Free header
        freeHeader = true;

        return 0x0;
    }
    else{
        return 0x1;
    }
}

void lin_send_header(lin_frame* frame)
{
    freeHeader = false;

    uint64_t lin_delay = get_lin_time();
    uint8_t id = lin_calculate_parity(frame->id);

    // Break
    gpio_set_function(txPin, GPIO_FUNC_SIO);
    gpio_put(txPin, false); // Send 0 for 14 TLIN
    sleep_us(LIN_BREAK_WIDTH * lin_delay);
    gpio_put(txPin, true);
    sleep_us(lin_delay);

    // Frame
    gpio_set_function(txPin, GPIO_FUNC_UART);

    // Prepare data
    uint8_t data[2] = {lin_sync, id};

    // Send
    uart_write_blocking(uart, data,2);

    // Check if is readable
    alarmId = add_alarm_in_us(get_lin_time() * 512, lin_not_received, nullptr, false);

    // Try to read frame
    if(!lin_read_frame_blocking(frame))
    {
        for(uint8_t q = 0; q < lin_get_data_size(id); q++)
            frame->data[q] = 0x0;
    }

    // Cancel alarm
    cancel_alarm(alarmId);
}

void lin_send_response(lin_frame* frame)
{
    // Calculate PID
    uint8_t id = lin_calculate_parity(frame->id);

    // Update settings
    gpio_set_function(txPin, GPIO_FUNC_UART);
    uint8_t checksum = calculate_checksum(id, frame->data, frame->length, frame->enhanced_checksum);

    uint8_t data_size = lin_get_data_size(id);

    // Build
    uint8_t data[9];
    for(int q = 0; q < data_size; q++)
        data[q] = frame->data[q];
    data[data_size] = checksum;

    // Send response
    uart_write_blocking(uart, data, frame->length + 1);
}

bool lin_read_frame_blocking(lin_frame *frame) {
    // Get timing
    uint64_t lin_delay = get_lin_time();
    gpio_set_function(rxPin, GPIO_FUNC_UART);
    uint8_t sync;
    uint8_t id;

    // Check if can be freed
    while(!uart_is_readable(uart)){
        if(freeHeader)
            return false;
    }

    // Break catcher
    uart_read_blocking(uart, &sync, 1);
    if(sync == 0x55){
        goto skip_sync;
    }

    if(sync != 0x0){
        gpio_set_function(rxPin, GPIO_FUNC_SIO);
        return false;
    }

    // Check if can be freed
    while(!uart_is_readable(uart)){
        if(freeHeader)
            return false;
    }

    // Invalid SYNC
    uart_read_blocking(uart, &sync, 1);
    if (sync != 0x55){
        gpio_set_function(rxPin, GPIO_FUNC_SIO);
        return false;
    }

    skip_sync:

    // Check if can be freed
    while(!uart_is_readable(uart)){
        if(freeHeader)
            return false;
    }

    uart_read_blocking(uart, &id, 1);

    frame->id = id;

    // Read data (if sent proper frame)
    if(uart_is_readable_within_us(uart, 16 * lin_delay))
    {
        uart_read_blocking(uart, frame->data, lin_get_data_size(id));
        uart_read_blocking(uart, &frame->checksum, 1);
    }

    gpio_set_function(rxPin, GPIO_FUNC_SIO);

    return true;

}

H:

#ifndef PICOUARTLIN_LIN_H
#define PICOUARTLIN_LIN_H

#include "pico/stdlib.h"
#include <hardware/uart.h>

struct lin_frame{
    uint8_t id;
    uint8_t* data;
    uint8_t length;
    bool enhanced_checksum;

    // Checksum only in received frames
    uint8_t checksum;
};

void lin_initialize(uart_inst_t* uartInst, uint tx, uint rx, uint baudRate);
void lin_send_frame(lin_frame* frame);
void lin_send_response(lin_frame* response);
bool lin_read_frame_blocking(lin_frame* frame);
void lin_send_header(lin_frame* frame);
uint8_t lin_get_data_size(uint8_t pid);
uint8_t lin_calculate_parity(uint8_t id);

#endif //PICOUARTLIN_LIN_H

 

1 godzinę temu, arow napisał:

Szkoda 🙂 Walczę z tym LIN BUS od 5 miesięcy i żadnego postępu :(. Cały czas odczytuje ale nic nie jestem w stanie wysłać. 

Możesz przejrzeć wcześniej podesłany kod. Wysyłanie działało bardzo dobrze, gorzej z odbiorem, bo czasem potrafił się przywiesić. Przepisanie tego na Arduino nie powinno być dużym problemem.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...