Microchip® Advanced Software Framework

Quick start guide for the SAM LIN module

This is the quick start guide for the LIN module, with step-by-step instructions on how to configure and use the driver in a selection of use cases.

The use cases contain several code fragments. The code fragments in the steps for setup can be copied into a custom initialization function, while the steps for usage can be copied into, e.g., the main application function.

LIN use cases

LIN master use case - Setup LIN master.

In this use case, the LIN node is set as a master PUBLISH. A specific data will be sent via it.

Prerequisites

  1. General Purpose I/O Management (gpio)
  2. Universal Synchronous Asynchronous Receiver Transmitter (USART)
  3. Timer Counter (TC)

Code

The following definitions must be added to the project.

#define LIN_FRAME_ID_12 0x12
#define LIN_TRANSFER_BYTE 0x55
#define LIN_MASTER_NODE_NUM 0
#define TC_CHANNEL 0
#define TC_FREQ 20

An array for the transfer bytes must be added:

uint8_t lin_data_node[8];

The Timer Counter are used to generate period cycle for the LIN master transfer. More information about how to configure and use TC can be found at sam_drivers_tc_group.

void configure_tc(void)
{
uint32_t ul_div;
uint32_t ul_tcclks;
static uint32_t ul_sysclk;
ul_sysclk = sysclk_get_cpu_hz();
tc_find_mck_divisor(TC_FREQ, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
tc_init(TC0, 0, ul_tcclks | TC_CMR_CPCTRG);
tc_write_rc(TC0, 0, (ul_sysclk / ul_div) / TC_FREQ);
NVIC_EnableIRQ((IRQn_Type)ID_TC0);
tc_enable_interrupt(TC0, 0, TC_IER_CPCS);
}

Add to application initialization:

{
pmc_enable_periph_clk(BOARD_ID_USART);
lin_desc.uc_id = LIN_FRAME_ID_12;
lin_desc.uc_dlc = sizeof(lin_data_node);
lin_desc.lin_cmd = PUBLISH;
lin_desc.uc_status = 0;
lin_desc.uc_pt_data = lin_data_node;
lin_register_desciptor(LIN_MASTER_NODE_NUM, 0, &lin_desc);
tc_start(TC0, 0);
}

Workflow

  1. LIN master node ID:
    #define LIN_FRAME_ID_12 0x12
  2. First data of the transfer:
    #define LIN_TRANSFER_BYTE 0x55
  3. Mater node number:
    #define LIN_MASTER_NODE_NUM 0
  4. Timer Counter channel number:
    #define TC_CHANNEL 0
  5. Timer Counter frequency:
    #define TC_FREQ 20
  6. Initialize system clock:
  7. Initialize board peripherals:
  8. Enable PMC for USART:
    pmc_enable_periph_clk(BOARD_ID_USART);
  9. Initialize LIN master, set the master with baudrate 9600:
  10. Set LIN master descriptor ID:
    lin_desc.uc_id = LIN_FRAME_ID_12;
  11. Set LIN master descriptor transfer size:
    lin_desc.uc_dlc = sizeof(lin_data_node);
  12. Set LIN master transfer type PUBLISHER:
    lin_desc.lin_cmd = PUBLISH;
  13. Set LIN master default transfer status:
    lin_desc.uc_status = 0;
  14. Set LIN master transfer data buffer:
    lin_desc.uc_pt_data = lin_data_node;
  15. Setup the master descriptor:
    lin_register_desciptor(LIN_MASTER_NODE_NUM, 0, &lin_desc);
  16. Initialize the Timer Counter:
  17. Start the Timer Counter:

Use case

Example code

Add to application C-file:

void TC0_Handler(void)
{
tc_get_status(TC0, 0);
lin_data_node[0] = LIN_FIRST_BYTE;
sizeof(lin_data_node));
}

Workflow

  1. The LIN master period is generated by TC interrupt service routine:
    void TC0_Handler(void)
  2. Clear Timer Counter status:
    tc_get_status(TC0, 0);
  3. Set the first byte of the transfer:
    lin_data_node[0] = LIN_FIRST_BYTE;
  4. Start the transfer:

LIN slave use case - Setup LIN slave.

In this use case, the LIN node is set as a slave subscriber. An LED will be flash when a specific data received.

Prerequisites

  1. General Purpose I/O Management (gpio)
  2. Universal Synchronous Asynchronous Receiver Transmitter (USART)
  3. Timer Counter (TC)

Workflow

The following definitions must be added to the project.

#define LIN_FRAME_ID_12 0x12
#define LIN_SPECIFIC_BYTE 0x55
#define LIN_SLAVE_NODE_NUM 0

An array for the received byte must be added:

uint8_t lin_data_node[8];

The usart0 interrupt service handler must be created to receive the LIN frame.

Add to application initialization:

{
pmc_enable_periph_clk(BOARD_ID_USART);
lin_init( USART0, false, LIN_SLAVE_NODE_NUM, 9600, sysclk_get_cpu_hz());
lin_desc.uc_id = LIN_FRAME_ID_12;
lin_desc.uc_dlc = sizeof(lin_data_node);
lin_desc.lin_cmd = SUBSCRIBE;
lin_desc.uc_status = 0;
lin_desc.uc_pt_data = lin_data_node;
lin_desc.pt_function = lin_slave_task_ID12;
lin_register_desciptor(LIN_MASTER_NODE_NUM, 0, &lin_desc);
NVIC_EnableIRQ(USART0_IRQn);
usart_enable_interrupt(USART0, US_IER_LINID);

Workflow

  1. LIN slave node ID:
    #define LIN_FRAME_ID_12 0x12
  2. Specific data to flash the LED:
    #define LIN_SPECIFIC_BYTE 0x55
  3. Slave node number:
    #define LIN_SLAVE_NODE_NUM 0
  4. Initialize system clock:
  5. Initialize board peripherals:
  6. Enable PMC for USART:
    pmc_enable_periph_clk(BOARD_ID_USART);
  7. Initialize LIN master, set the master with baudrate 9600:
    lin_init( USART0, false, LIN_SLAVE_NODE_NUM, 9600, sysclk_get_cpu_hz());
  8. Set LIN slave descriptor ID:
    lin_desc.uc_id = LIN_FRAME_ID_12;
  9. Set LIN master descriptor transfer size:
    lin_desc.uc_dlc = sizeof(lin_data_node);
  10. Set LIN slave transfer type SUBSCRIBE:
    lin_desc.lin_cmd = SUBSCRIBE;
  11. Set LIN master default transfer status:
    lin_desc.uc_status = 0;
  12. Set LIN slave transfer data buffer:
    lin_desc.uc_pt_data = lin_data_node;
  13. Set LIN slave task handle:
    lin_desc.pt_function = lin_slave_task_ID12;
  14. Setup the salve descriptor:
    lin_register_desciptor(LIN_SLAVE_NODE_NUM, 0, &lin_desc);

Use case

Example code

Add to application C-file:

void lin_slave_task_ID12(uint8_t *uc_buf)
{
if (uc_buf[0] == LIN_SPECIFIC_BYTE) {
}
}

Workflow

  1. The slave task is defined in the LIN descriptor.
    void lin_slave_task_ID12(uint8_t *uc_buf)
  2. Check if received the spcific byte and flash the LED.
    if (uc_buf[0] == LIN_SPECIFIC_BYTE) {
    }