Commit e2bcc8f4 authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Merge branch 'can_devel' into 'master'

Can devel

See merge request !13
parents ed41fcd1 099671b6
#ifndef CAN_F1_H
#define CAN_F1_H
#include "stm32f1xx_hal.h"
#include "comm.h"
typedef struct
{
unsigned char irq_priority;
unsigned char irq_subpriority;
}TCAN_IRQ_Priorities;
typedef enum
{
CAN_10KBPS,
CAN_20KBPS,
CAN_50KBPS,
CAN_83K3BPS,
CAN_100KBPS,
CAN_125KBPS,
CAN_250KBPS,
CAN_500KBPS,
CAN_1000KBPS
} CAN_SPEED;
typedef enum
{
VERSION_1,
VERSION_2,
VERSION_NULL
} DynamixelVersion;
typedef struct TDynamixelMessage
{
unsigned char received_bytes;
/**
* \brief
*
*/
unsigned char rx_buffer[MAX_DYN_SLAVE_RX_BUFFER_LEN];
/**
* \brief
*
*/
unsigned char Len_L;
/**
* \brief
*
*/
unsigned char Len_H;
/**
* \brief
*
*/
unsigned int length;
/**
* \brief
*
*/
DynamixelVersion version;
/**
* \brief
*
*/
unsigned char packet_init;
/**
* \brief
*
*/
unsigned char packet_incomplete;
/**
* \brief
*
*/
unsigned char send_packet;
/**
* \brief
*
*/
unsigned char iterations;
/**
* \brief
*
*/
}TDynamixelMessage;
/* public functions */
void can_init(TComm *comm_dev,CAN_InitTypeDef *conf,TCAN_IRQ_Priorities *priorities);
void can_config(TComm *comm_dev,CAN_InitTypeDef *conf);
void can_set_priorities(TComm *comm_dev,TCAN_IRQ_Priorities *priorities);
void can_set_bitrate(TComm *comm_dev,CAN_SPEED bitrate);
void can_set_filter(TComm *comm_dev,CAN_FilterConfTypeDef *filter);
void can_set_can_id(TComm *comm_dev,unsigned char id);
/* IRQ functions */
unsigned char can_send_irq(unsigned char first_byte);
unsigned char can_enable_tx_irq(void);
unsigned char can_receive_irq(void);
unsigned char can_cancel_receive_irq(void);
/* DMA functions */
unsigned char can_send_dma(unsigned char *data,unsigned short int length);
unsigned char can_receive_dma(unsigned char *data,unsigned short int length);
unsigned char can_cancel_receive_dma(void);
#endif
#ifndef CAN_COMMON_F1_H
#define CAN_COMMON_F1_H
typedef struct
{
unsigned char irq_priority;
unsigned char irq_subpriority;
}TCAN_IRQ_Priorities;
enum CAN_SPEED { //only applies when APB1 = 36Mhz
CAN_10KBPS,
CAN_20KBPS,
CAN_50KBPS,
CAN_83K3BPS,
CAN_100KBPS,
CAN_125KBPS,
CAN_250KBPS,
CAN_500KBPS,
CAN_1000KBPS
};
#endif
#include "can.h"
#define CAN CAN1
#define CAN_ENABLE_CLK __HAL_RCC_CAN1_CLK_ENABLE()
#define CAN_IRQnRX USB_LP_CAN1_RX0_IRQn
#define CAN_IRQnTX USB_HP_CAN1_TX_IRQn
#define CAN_IRQHandler USB_LP_CAN1_RX0CAN_IRQHandler
#define CAN_TX_PIN GPIO_PIN_9
#define CAN_TX_GPIO_PORT GPIOB
#define CAN_ENABLE_TX_GPIO_CLK __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN_RX_PIN GPIO_PIN_8
#define CAN_RX_GPIO_PORT GPIOB
#define CAN_ENABLE_RX_GPIO_CLK __HAL_RCC_GPIOB_CLK_ENABLE()
// private variables
CAN_HandleTypeDef CANHandle;
CAN_FilterConfTypeDef CANFilterConfig;
CanTxMsgTypeDef CAN_txMessage;
CanRxMsgTypeDef CAN_rxMessage;
TComm *can_comm_dev;
unsigned char can_dma_phase;
unsigned char *can_dma_phase_data;
unsigned short int can_dma_phase_length;
unsigned short int can_dma_phase_write_ptr;
unsigned char can_missing_bytes_data[255];
unsigned short int can_missing_bytes_length;
unsigned short int can_missing_bytes_write_ptr;
unsigned short int can_send_lenght;
unsigned short int can_send_iterations;
unsigned char can_send_data[255];
TDynamixelMessage message;
// 1
void can_init(TComm *comm_dev,CAN_InitTypeDef *conf,TCAN_IRQ_Priorities *priorities)
{
CANHandle.Instance = CAN1;
can_config(comm_dev,conf);
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIO clock */
CAN_ENABLE_TX_GPIO_CLK;
CAN_ENABLE_RX_GPIO_CLK;
CAN_ENABLE_CLK;
/**CAN GPIO Configuration
PB8 ------> CAN_RX
PB9 ------> CAN_TX
*/
/* Configure CAN Tx and Rx as alternate function push-pull */
GPIO_InitStructure.Pin = CAN_RX_PIN;
GPIO_InitStructure.Pull = GPIO_MODE_INPUT;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = CAN_TX_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);
__HAL_AFIO_REMAP_CAN1_2();
can_set_priorities(comm_dev,priorities);
HAL_CAN_Init(&CANHandle);
/* Initialize the comm structure */
comm_dev->send_irq=can_send_irq;
comm_dev->enable_tx_irq=can_enable_tx_irq;
comm_dev->receive_irq=can_receive_irq;
comm_dev->cancel_receive_irq=can_cancel_receive_irq;
if(comm_dev->use_dma)
{
comm_dev->send_dma=can_send_dma;
comm_dev->receive_dma=can_receive_dma;
comm_dev->cancel_receive_dma=can_cancel_receive_dma;
}
comm_dev->irq_send_cb=0x00000000;
comm_dev->irq_receive_cb=0x00000000;
comm_dev->dma_send_cb=0x00000000;
comm_dev->dma_receive_cb=0x00000000;
// /* initialize internal variables */
can_comm_dev=comm_dev;
can_dma_phase=0x00;
can_dma_phase_data=0x00;
can_dma_phase_length=0;
can_dma_phase_write_ptr=0;
can_missing_bytes_length = 0;
can_missing_bytes_write_ptr = 0;
can_send_lenght = 0;
can_send_iterations = 0;
message.packet_init = 0x00;
message.packet_incomplete = 0x00;
message.send_packet = 0x00;
message.iterations = 0;
///////////////////////////////////////////////////////////////////////////
CANFilterConfig.FilterNumber = 0;
CANFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
CANFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
CANFilterConfig.FilterIdHigh = 0x0000;
CANFilterConfig.FilterIdLow = 0x0000;
CANFilterConfig.FilterMaskIdHigh = 0x0000;
CANFilterConfig.FilterMaskIdLow = 0x0000;
CANFilterConfig.FilterFIFOAssignment = 0;
CANFilterConfig.FilterActivation = ENABLE;
CANFilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&CANHandle, &CANFilterConfig);
CANHandle.pRxMsg = &CAN_rxMessage;
CANHandle.pTxMsg = &CAN_txMessage;
CANHandle.pTxMsg->StdId = 0x00;
CANHandle.pTxMsg->ExtId = 0x01;
CANHandle.pTxMsg->RTR = CAN_RTR_DATA;
CANHandle.pTxMsg->IDE = CAN_ID_STD;
//HAL_CAN_Receive_IT(&CANHandle,CAN_FIFO0);
}
void can_config(TComm *comm_dev,CAN_InitTypeDef *conf)
{
CANHandle.Init.Prescaler = conf->Prescaler;
CANHandle.Init.Mode = conf->Mode;
CANHandle.Init.SJW = conf->SJW;
CANHandle.Init.BS1 = conf->BS1;
CANHandle.Init.BS2 = conf->BS2;
CANHandle.Init.TTCM = conf->TTCM;
CANHandle.Init.ABOM = conf->ABOM;
CANHandle.Init.AWUM = conf->AWUM;
CANHandle.Init.NART = conf->NART;
CANHandle.Init.RFLM = conf->RFLM;
CANHandle.Init.TXFP = conf->TXFP;
}
void can_set_priorities(TComm *comm_dev,TCAN_IRQ_Priorities *priorities)
{
HAL_NVIC_SetPriority(CAN_IRQnRX, priorities->irq_priority, priorities->irq_subpriority);
HAL_NVIC_EnableIRQ(CAN_IRQnRX);
HAL_NVIC_SetPriority(CAN_IRQnTX, priorities->irq_priority, priorities->irq_subpriority);
HAL_NVIC_EnableIRQ(CAN_IRQnTX);
}
void can_set_bitrate(TComm *comm_dev,CAN_SPEED bitrate)
{
switch (bitrate) {
case CAN_10KBPS:
CANHandle.Init.Prescaler = 225;
CANHandle.Init.BS1 = CAN_BS1_13TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_20KBPS:
CANHandle.Init.Prescaler = 100;
CANHandle.Init.BS1 = CAN_BS1_15TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_50KBPS:
CANHandle.Init.Prescaler = 45;
CANHandle.Init.BS1 = CAN_BS1_13TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_83K3BPS:
CANHandle.Init.Prescaler = 27;
CANHandle.Init.BS1 = CAN_BS1_13TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_100KBPS:
CANHandle.Init.Prescaler = 20;
CANHandle.Init.BS1 = CAN_BS1_15TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_125KBPS:
CANHandle.Init.Prescaler = 18;
CANHandle.Init.BS1 = CAN_BS1_13TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_250KBPS:
CANHandle.Init.Prescaler = 9;
CANHandle.Init.BS1 = CAN_BS1_13TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_500KBPS:
CANHandle.Init.Prescaler = 4;
CANHandle.Init.BS1 = CAN_BS1_15TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
case CAN_1000KBPS:
CANHandle.Init.Prescaler = 2;
CANHandle.Init.BS1 = CAN_BS1_15TQ;
CANHandle.Init.BS2 = CAN_BS2_2TQ;
CANHandle.Init.SJW = CAN_SJW_1TQ;
break;
}
}
void can_set_filter(TComm *comm_dev,CAN_FilterConfTypeDef *filter)
{
HAL_CAN_ConfigFilter(&CANHandle, filter);
//HAL_CAN_Receive_IT(&CANHandle,CAN_FIFO0);
}
void can_set_can_id(TComm *comm_dev,unsigned char id)
{
CANHandle.pTxMsg->StdId = id;
}
/**
* HAL_CAN_ErrorCallback
* Callback function for CAN errors.
* @param CANHandle Pointer to a CAN_HandleTypeDef structure that contains
* the configuration information for a given CAN peripheral.
*/
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef* CANHandle)
{
//HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET);
}
void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* CANHandle)
{
// HAL_CAN_StateTypeDef status = HAL_CAN_GetState(CANHandle);
// while(HAL_CAN_STATE_READY != status)
// {
// status = HAL_CAN_GetState(CANHandle);
// }
if (can_send_lenght != 0)
{
if (can_send_lenght > 8)
{
for (uint8_t i=0;i<8;i++)
{
CANHandle->pTxMsg->Data[i] = can_send_data[i+(8*can_send_iterations)];
}
can_send_lenght = can_send_lenght - 8;
can_send_iterations++;
HAL_CAN_Transmit_IT(CANHandle);
}
else
{
for (uint8_t i=0;i<can_send_lenght;i++)
{
CANHandle->pTxMsg->Data[i] = can_send_data[i+(8*can_send_iterations)];
}
can_send_lenght = 0;
can_send_iterations = 0;
HAL_CAN_Transmit_IT(CANHandle);
uint8_t byte;
comm_do_dma_send(can_comm_dev);
comm_do_irq_send(can_comm_dev,&byte);
}
}
//__HAL_CAN_DISABLE_IT(CANHandle,CAN_IT_TME);
__HAL_CAN_CLEAR_FLAG(CANHandle,CAN_FLAG_RQCP0);
__HAL_CAN_CLEAR_FLAG(CANHandle,CAN_FLAG_TXOK0);
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CANHandle)
{
if(can_missing_bytes_length == 0){
for(uint8_t i=0;i<CAN_rxMessage.DLC;i++)
{
if(!can_dma_phase)
comm_do_irq_receive(can_comm_dev,CAN_rxMessage.Data[i]);
else
{
if(can_dma_phase_length<5){
can_dma_phase_data[can_dma_phase_write_ptr]=CAN_rxMessage.Data[i];
can_dma_phase_length--;
can_dma_phase_write_ptr++;
if(can_dma_phase_length==0){
comm_do_dma_receive(can_comm_dev);
}
}
}
}
if(can_dma_phase_length>4){
for(uint8_t i=0;i<CAN_rxMessage.DLC;i++)
can_missing_bytes_data[i] = CAN_rxMessage.Data[i];
can_missing_bytes_length = can_dma_phase_length-4;
can_missing_bytes_write_ptr = 7;
}
}
else
{
if(can_missing_bytes_length<=8){
for(uint8_t i=0;i<CAN_rxMessage.DLC;i++)
{
can_missing_bytes_write_ptr++;
can_missing_bytes_length--;
can_missing_bytes_data[can_missing_bytes_write_ptr] = CAN_rxMessage.Data[i];
}
for(uint8_t i=0;i<=can_missing_bytes_write_ptr;i++)
{
if(!can_dma_phase)
comm_do_irq_receive(can_comm_dev,can_missing_bytes_data[i]);
else
{
can_dma_phase_data[can_dma_phase_write_ptr]=can_missing_bytes_data[i];
can_dma_phase_length--;
can_dma_phase_write_ptr++;
if(can_dma_phase_length==0){
comm_do_dma_receive(can_comm_dev);
can_missing_bytes_length = 0;
can_missing_bytes_write_ptr = 0;
}
}
}
}
else
{
for(uint8_t i=0;i<CAN_rxMessage.DLC;i++)
{
can_missing_bytes_write_ptr++;
can_missing_bytes_length--;
can_missing_bytes_data[can_missing_bytes_write_ptr] = CAN_rxMessage.Data[i];
}
}
}
}
// interrupt handlers
void USB_LP_CAN1_RX0_IRQHandler(void)
{
/* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */
/* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&CANHandle);
/* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */
/* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */
}
void USB_HP_CAN1_TX_IRQHandler(void)
{
/* USER CODE BEGIN USB_HP_CAN1_TX_IRQn 0 */
/* USER CODE END USB_HP_CAN1_TX_IRQn 0 */
HAL_CAN_IRQHandler(&CANHandle);
/* USER CODE BEGIN USB_HP_CAN1_TX_IRQn 1 */
/* USER CODE END USB_HP_CAN1_TX_IRQn 1 */
}
unsigned char can_send_irq(unsigned char first_byte)
{
return 0x00;
}
unsigned char can_enable_tx_irq(void)
{
return 0x00;
}
unsigned char can_receive_irq(void)
{
can_dma_phase=0x00;
can_dma_phase_write_ptr=0x00;
HAL_CAN_Receive_IT(&CANHandle,CAN_FIFO0);
return 0x00;
}
unsigned char can_cancel_receive_irq(void)
{
return 0x00;
}
/* DMA functions */
unsigned char can_send_dma(unsigned char *data,unsigned short int length)
{
// if (length <= 8)
// {
// CANHandle.pTxMsg->DLC = length;
// for (uint8_t i=0;i<length;i++)
// {
// CANHandle.pTxMsg->Data[i] = data[i];
// }
// HAL_CAN_Transmit_IT(&CANHandle);
// }
// else
// {
// unsigned char iterations = 0x00;
// while (length > 0)
// {
// if(length > 8)
// CANHandle.pTxMsg->DLC = 8;
// else
// CANHandle.pTxMsg->DLC = length;
// for (uint8_t i=0;i<CANHandle.pTxMsg->DLC;i++)
// {
// CANHandle.pTxMsg->Data[i] = data[i+iterations];
// }
// HAL_CAN_Transmit_IT(&CANHandle);
// HAL_Delay(5);
// iterations = iterations + 8;
// length = length - CANHandle.pTxMsg->DLC;
// }
// }
if(length > 8){
CANHandle.pTxMsg->DLC = 8;
for (uint8_t i=0;i<length;i++)
{
can_send_data[i] = data[i];
}
can_send_lenght = length - 8;
can_send_iterations = 1;
for (uint8_t i=0;i<8;i++)
{
CANHandle.pTxMsg->Data[i] = data[i];
}
HAL_CAN_Transmit_IT(&CANHandle);
}
else{
CANHandle.pTxMsg->DLC = length;
for (uint8_t i=0;i<length;i++)
{
CANHandle.pTxMsg->Data[i] = data[i];
}
HAL_CAN_Transmit_IT(&CANHandle);
uint8_t byte;
comm_do_dma_send(can_comm_dev);
comm_do_irq_send(can_comm_dev,&byte);
}
//HAL_CAN_Transmit_IT(&CANHandle);
__HAL_CAN_CLEAR_FLAG(&CANHandle,CAN_FLAG_RQCP0);
__HAL_CAN_CLEAR_FLAG(&CANHandle,CAN_FLAG_TXOK0);
return 0x00;
}
unsigned char can_receive_dma(unsigned char *data,unsigned short int length)
{
can_dma_phase=0x01;
can_dma_phase_data=data;
can_dma_phase_length=length;
can_dma_phase_write_ptr=0;
return 0x00;
}
unsigned char can_cancel_receive_dma(void)
{
can_dma_phase=0x00;
can_dma_phase_data=0x00;
can_dma_phase_length=0;
can_dma_phase_write_ptr=0;
return 0x00;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment