Carte Nucleo F103

nucleo-f103.jpg

User Manual STM32F103

REMARQUE

On note dans les spécifications :
USB re-enumeration capability: three different interfaces supported on USB

  • Virtual Com port /dev/ttyACM0
  • Mass storage
  • Debug port

Autrement dit il sera possible via le câble USB de communiquer en RS232 (périphérique UART sur la carte) et d’effectuer le Debug JTAG (chargement de l’exécutable / exécution / point d’arrêt / visualisation de la mémoire et des registres).

virtual_com.svg


Périphériques

peripheriques.svg


Environnement de Développement

STM32CubeIDE


Sources du Projet

WORKSPACE_RESCAPT_STM32CUBEIDE.zip


Bus CAN

Driver BUS CAN
/*
 * can_bus.h
 *
 *  Created on: 10 sept. 2015
 *      Author: kerhoas
 */

#ifndef INC_DRV_CAN_H_
#define INC_DRV_CAN_H_

#include "main.h"
#include "can_bus_types.h"

//********************************************************************



//********************************************************************

typedef enum {
    IRQ_RX,
    IRQ_TX,
    IRQ_ERROR,
    IRQ_OVERRUN,
    IRQ_WAKEUP,
    IRQ_PASSIVE,
    IRQ_ARB,
    IRQ_BUS,
    IRQ_READY
} CanIrqType;


typedef enum {
    MODE_RESET,
    MODE_NORMAL,
    MODE_SILENT,
    MODE_TEST_GLOBAL,
    MODE_TEST_LOCAL,
    MODE_TEST_SILENT
} CanMode;

typedef struct can_s can_t;

void          can_Init(void);
int           can_SetFreq(int hz);

void          can_IrqInit(void);
void          can_IrqFree(void);
void          can_IrqSet(void (*fptr)(void));

int           can_Write(CAN_Message);
int           can_Read(CAN_Message *msg);
int           can_Mode(CanMode mode);
int 		  can_Filter_list(uint32_t id1_id2, uint32_t id3_id4, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ );
int 		  can_Filter_disable();
void          can_Reset(void);
unsigned char can_Rderror(void);
unsigned char can_Tderror(void);


#endif /* INC_DRV_CAN_H_ */
/*
 * can_bus.c
 *
 *  Created on: 10 sept. 2015
 *      Author: kerhoas
 */

#include "drv_can.h"

#pragma GCC optimize ("O0")

extern void (*rxCompleteCallback) (void);
CAN_HandleTypeDef    CanHandle;
CanRxMsgTypeDef     canRxMsg;
CanTxMsgTypeDef     canTxMsg;

extern void can_callback(void);

//===========================================================================
// INIT CAN
//===========================================================================
void can_Init()
{
	CanHandle.Instance = CAN1;
	CanHandle.pTxMsg = &canTxMsg;
	CanHandle.pRxMsg = &canRxMsg;

	CanHandle.Init.TTCM = DISABLE;
	CanHandle.Init.ABOM = DISABLE;
	CanHandle.Init.AWUM = DISABLE;
	CanHandle.Init.NART = DISABLE;
	CanHandle.Init.RFLM = DISABLE;
	CanHandle.Init.TXFP = DISABLE;
	CanHandle.Init.Mode = CAN_MODE_NORMAL;

	// 125kbps bit rate (default)
	// APB1 peripheral clock = 36000000Hz
	CanHandle.Init.Prescaler = 18;      // number of time quanta = 36000000/18/125000 = 16
	CanHandle.Init.SJW = CAN_SJW_1TQ;
	CanHandle.Init.BS1 = CAN_BS1_11TQ;  // sample point at (1 + 11) / 16 * 100 = 75%
	CanHandle.Init.BS2 = CAN_BS2_4TQ;

	HAL_CAN_Init(&CanHandle);
	can_IrqSet(can_callback);
	
//	can_Filter(0, 0, CANAny, 0);
}

//===========================================================================
int can_SetFreq(int hz) {

    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
    // APB1 peripheral clock = 36000000Hz
    switch(hz) {
    case 1000000:
        // 1000kbps bit rate
        CanHandle.Init.Prescaler = 3;//3;      // number of time quanta = 36000000/3/1000000 = 12
        CanHandle.Init.SJW = CAN_SJW_1TQ;
        CanHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
        CanHandle.Init.BS2 = CAN_BS2_3TQ;
        break;
    case 500000:
        // 500kbps bit rate
        CanHandle.Init.Prescaler = 6;      // number of time quanta = 36000000/6/500000 = 12
        CanHandle.Init.SJW = CAN_SJW_1TQ;
        CanHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
        CanHandle.Init.BS2 = CAN_BS2_3TQ;
        break;
    case 250000:
        // 250kbps
        CanHandle.Init.Prescaler = 9;      // number of time quanta = 36000000/9/250000 = 16
        CanHandle.Init.SJW = CAN_SJW_1TQ;
        CanHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
        CanHandle.Init.BS2 = CAN_BS2_4TQ;
        break;
    case 125000:
        // 125kbps
        CanHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
        CanHandle.Init.SJW = CAN_SJW_1TQ;
        CanHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
        CanHandle.Init.BS2 = CAN_BS2_4TQ;
        break;
    default:
        // 125kbps (default)
        CanHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
        CanHandle.Init.SJW = CAN_SJW_1TQ;
        CanHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
        CanHandle.Init.BS2 = CAN_BS2_4TQ;
    }

    HAL_CAN_Init(&CanHandle);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);

    return 1;
}
//===========================================================================

void can_IrqInit(void)
{
	HAL_CAN_Receive_IT(&CanHandle, CAN_FIFO0);
}

//===========================================================================
void can_IrqFree()
{
    rxCompleteCallback = NULL;
}
//===========================================================================
void can_IrqSet(void (*fptr) (void))
{
    rxCompleteCallback = fptr;
}
//===========================================================================
int can_Write(CAN_Message msg)
{
    int i = 0;

    if(msg.format == CANStandard) {
        CanHandle.pTxMsg->StdId = msg.id;
        CanHandle.pTxMsg->ExtId = 0x00;
    }
    else {
        CanHandle.pTxMsg->StdId = 0x00;
        CanHandle.pTxMsg->ExtId = msg.id;
    }

    CanHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE;
    CanHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT;
    CanHandle.pTxMsg->DLC = msg.len;

    for(i = 0; i < msg.len; i++)
        CanHandle.pTxMsg->Data[i] = msg.data[i];

    if(HAL_CAN_Transmit(&CanHandle, 0) != HAL_OK)
							{
								 return 0;
							 }

    else
        return 1;
}
//===========================================================================
int can_Read(CAN_Message* msg)
{
	int i=0;

    msg->id = CanHandle.pRxMsg->IDE == CAN_ID_STD ? CanHandle.pRxMsg->StdId : CanHandle.pRxMsg->ExtId;
    msg->type = CanHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote;
    msg->format = CanHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended;
    msg->len = CanHandle.pRxMsg->DLC;
    for(i = 0; i < msg->len; i++)
        msg->data[i] = CanHandle.pRxMsg->Data[i];

    return msg->len;
}
//===========================================================================
int can_Mode(CanMode mode)
{
    switch(mode) {
    case MODE_RESET:
        return HAL_ERROR;

    case MODE_NORMAL:
        CanHandle.Init.Mode = CAN_MODE_NORMAL;
        break;

    case MODE_SILENT:
        CanHandle.Init.Mode = CAN_MODE_SILENT;
        break;

    case MODE_TEST_GLOBAL:
        CanHandle.Init.Mode = CAN_MODE_LOOPBACK;
        break;

    case MODE_TEST_LOCAL:
        CanHandle.Init.Mode = CAN_MODE_LOOPBACK;
        break;

    case MODE_TEST_SILENT:
        CanHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
        break;
    }

    return HAL_CAN_Init(&CanHandle);
}
//===========================================================================
int can_Filter_list(uint32_t id1_id2, uint32_t id3_id4, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ )
{
    CAN_FilterConfTypeDef   sFilterConfig;

    sFilterConfig.FilterNumber = handle;
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;  // CAN_FILTERMODE_IDMASK
    
    sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // CAN_FILTERSCALE_32BIT
    sFilterConfig.FilterIdHigh = (((id1_id2) >> 16) & 0xFFFF);
    sFilterConfig.FilterIdLow = ((id1_id2) & 0xFFFF);
    sFilterConfig.FilterMaskIdHigh = (((id3_id4) >> 16) & 0xFFFF);
    sFilterConfig.FilterMaskIdLow = ((id3_id4) & 0xFFFF);
    sFilterConfig.FilterFIFOAssignment = 0;
    sFilterConfig.FilterActivation = ENABLE;
    sFilterConfig.BankNumber = 14;
    HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig);

    return 1;
}

//===========================================================================
int can_Filter_disable()
{
    CAN_FilterConfTypeDef   sFilterConfig;

    sFilterConfig.FilterNumber = 0;
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;

    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0;
    sFilterConfig.FilterIdLow = 0;
    sFilterConfig.FilterMaskIdHigh = 0;
    sFilterConfig.FilterMaskIdLow = 0;
    sFilterConfig.FilterFIFOAssignment = 0;
    sFilterConfig.FilterActivation = ENABLE;
    sFilterConfig.BankNumber = 14;
    HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig);

    return 1;
}


//===========================================================================
void can_Reset()
{
    __HAL_CAN_RESET_HANDLE_STATE(&CanHandle);
}
//===========================================================================
unsigned char can_Rderror()
{
    return HAL_CAN_GetError(&CanHandle);
}
//===========================================================================
unsigned char can_Tderror()
{
    return HAL_CAN_GetError(&CanHandle);
}
//===========================================================================

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
    if (rxCompleteCallback != NULL)
        rxCompleteCallback();

    if (CanHandle->State == HAL_CAN_STATE_BUSY_TX)
        CanHandle->State = HAL_CAN_STATE_BUSY_TX_RX;
    else {
        CanHandle->State = HAL_CAN_STATE_BUSY_RX;

        /* Set CAN error code to none */
        CanHandle->ErrorCode = HAL_CAN_ERROR_NONE;

        /* Enable Error warning Interrupt */
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EWG);

        /* Enable Error passive Interrupt */
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EPV);

        /* Enable Bus-off Interrupt */
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_BOF);

        /* Enable Last error code Interrupt */
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_LEC);

        /* Enable Error Interrupt */
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_ERR);
    }

    // Enable FIFO 0 message pending Interrupt
    __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_FMP0);
}