CUBEMX+CANOPEN教程二:can機能コード完備
8023 ワード
チュートリアルの基礎の上でcanの機能の完備を行います
主な仕事: canフィルタ構成 can受信関連構造体構築 を送信する. can送信と受信などの関数構築 can festival移植 タイマ構成 文書ディレクトリ 1. canフィルタ構成 2. can受信に関するデータ構造構築 を送信する. 3. can送信と受信などの関数構築 4. can festival移植 5. タイマ構成 小結 1.canフィルタ構成
bsp_can.cファイルに追加
2.can受信に関するデータ構造構築の送信
CAN 1送信と受信データフレームヘッダ定義は標準ライブラリと異なる
ここでMessageは構造体がcanである.hファイルでの定義
3.can送受信等の関数構築
送信関数
can受信キュー保留割込みコールバック関数
以上のコードの最後の3行の3つのログアウト関数に注意して、1つ目はcanopenネットワークホストがデータを受信することを分析して、実際のプロジェクトの応用です;2つ目は印刷で、重要ではありません.3つ目はcanopenメッセージ分析で、重要です.
4.can festival移植
ソースコードを分析すると、canopen実装の最も重要なのは、canopenネットワークのメッセージの送信と受信タイミングと裁決をタイマで制御することであることがわかる.can festivalを移植した後、主にタイマがfestivalソースコードに融合するためのタイマ機能について話します.
5.タイマー構成
タイミングは1 ms
bsp_timer.cではいくつかの関数を実現し、主にfestivalソースコードに呼び出しを提供する.タイマー設定自動リロード値 を実現する.実装タイマは、現在のカウント値 を得る.タイマ初期化関数 を実現する.タイマ比較出力割り込みコールバック関数 を実現する.
そのうち#define CANOPEN_MYはもうmainにいます.hファイルでは、タイマオンはメイン関数ではなくfestivalソースコードでオンタイマを呼び出すように定義されています.
メイン関数の初期化時にcanopenネットワークの初期化を呼び出し、
ソースコードのcan初期化はボーレートを構成することができ、cubemxでボーレートが構成されているべきであるため、
この関数はcubemxで生成されたcan初期化関数を呼び出し,自分で実現したcanフィルタ初期化関数を加える.
これでcan festival移植が完了し、canopen通信ネットワークホスト機能が実現しました.
小結
主な仕事:
bsp_can.cファイルに追加
void CAN_Filter_Init(void)
{
CAN_FilterTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.FilterActivation = ENABLE;
CAN_FilterInitStructure.FilterBank = 0;
CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FILTER_FIFO0;
CAN_FilterInitStructure.FilterIdHigh = 0x0000;
CAN_FilterInitStructure.FilterIdLow = 0x0000;
CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterInitStructure.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan1, &CAN_FilterInitStructure) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if(HAL_CAN_Start(&hcan1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
2.can受信に関するデータ構造構築の送信
CAN 1送信と受信データフレームヘッダ定義は標準ライブラリと異なる
/* bsp_can.c */
/* CAN1 */
CAN_TxHeaderTypeDef CAN1_TxHeaderMessage;
CAN_RxHeaderTypeDef CAN1_RxHeaderMessage;
/* CAN1 */
CAN_Msgdata can1_tx_msg;
CAN_Msgdata can1_rx_msg;
/* bsp_can.h */
typedef struct{
Message m;
}CANOpen_Message;
typedef struct
{
uint8_t Data[8];
}CAN_Msgdata;
ここでMessageは構造体がcanである.hファイルでの定義
/* can.h */
typedef struct {
UNS16 cob_id; /**< message's ID */
UNS8 rtr; /**< remote transmission request. (0 if not rtr message, 1 if rtr message) */
UNS8 len; /**< message's length (0 to 8) */
UNS8 data[8]; /**< message's datas */
} Message;
#define Message_Initializer {0,0,0,{0,0,0,0,0,0,0,0}}
typedef UNS8 (*canSend_t)(Message *);
3.can送受信等の関数構築
送信関数
/* bsp_can.c */
u8 canSend(CAN_HandleTypeDef *hcan,Message *m)
{
unsigned char i;
CAN_TxHeaderTypeDef TxMessage;
TxMessage.StdId = (uint32_t)(m->cob_id);
TxMessage.ExtId = 0x00;
TxMessage.RTR = m->rtr;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.DLC = m->len;
for(i=0;ilen;i++)
{
can1_tx_msg.Data[i] = m->data[i];
}
if(HAL_CAN_AddTxMessage(&hcan1, &TxMessage, can1_tx_msg.Data, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK)
{
return 1;
// printf(" \r
");
// _Error_Handler(__FILE__, __LINE__);
}
return 0;
}
can受信キュー保留割込みコールバック関数
/* bsp_can.c */
CANOpen_Message CAN1_Rx_m;
Message RxMSG = Message_Initializer;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance == CAN1)
{
/* can */
HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0, &CAN1_RxHeaderMessage, can1_rx_msg.Data);
/* can canDispatch */
RxMSG.cob_id = CAN1_RxHeaderMessage.StdId;
RxMSG.len = CAN1_RxHeaderMessage.DLC;
RxMSG.rtr = CAN1_RxHeaderMessage.RTR;
memcpy(RxMSG.data,can1_rx_msg.Data,CAN1_RxHeaderMessage.DLC);
}
// AnalysisMessagefromDriver();
// SEGGER_RTT_printf(0, "can master revcive data!!!!!!!!!!!!
");
// canDispatch(CANOpenMasterObject, &(RxMSG));
}
以上のコードの最後の3行の3つのログアウト関数に注意して、1つ目はcanopenネットワークホストがデータを受信することを分析して、実際のプロジェクトの応用です;2つ目は印刷で、重要ではありません.3つ目はcanopenメッセージ分析で、重要です.
4.can festival移植
ソースコードを分析すると、canopen実装の最も重要なのは、canopenネットワークのメッセージの送信と受信タイミングと裁決をタイマで制御することであることがわかる.can festivalを移植した後、主にタイマがfestivalソースコードに融合するためのタイマ機能について話します.
5.タイマー構成
タイミングは1 ms
/* tim.c */
/* TIM4 init function */
void MX_TIM4_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
htim4.Instance = TIM4;
htim4.Init.Prescaler = 84-1;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 1000-1;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_OC_Init(&htim4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_OC_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
bsp_timer.cではいくつかの関数を実現し、主にfestivalソースコードに呼び出しを提供する.
#ifdef CANOPEN_MY
#include
#include "canfestival.h"
#include "timer.h"
#endif
#ifdef CANOPEN_MY
static TIMEVAL last_time_set = TIMEVAL_MAX;
/**
* @brief setTimer
* @param value:Set time value 0x0000-0xffff
* @retval NONE
*/
void setTimer(TIMEVAL value)
{
__HAL_TIM_SetAutoreload(&htim4, value);
}
/**
* @brief getElapsedTime
* @param NONE
* @retval TIMEVAL:Return current timer value
*/
TIMEVAL getElapsedTime(void)
{
uint16_t timer = __HAL_TIM_GetCounter(&htim4);
return timer > last_time_set ? timer - last_time_set : last_time_set - timer;
}
/**
* @brief TIM4_start
* @param NONE
* @retval NONE
*/
void TIM4_start(void)
{
MX_TIM4_Init();
}
/**
* @brief initTimer
* @param NONE
* @retval NONE
*/
void initTimer(void)
{
TIM4_start();
}
そのうち#define CANOPEN_MYはもうmainにいます.hファイルでは、タイマオンはメイン関数ではなくfestivalソースコードでオンタイマを呼び出すように定義されています.
/* CANOpenObjDictConfig.c */
void Master_operational(CO_Data* d)
{
UNS32 SyncTimePeriod = 2000;
UNS32 size = sizeof(SyncTimePeriod);
writeLocalDict( d, /*CO_Data* d*/
0x1006, /*UNS16 index*/
0x00, /*UNS8 subind*/
&SyncTimePeriod, /*void * pSourceData,*/
&size, /* UNS8 * pExpectedSize*/
RW); /* UNS8 checkAccess */
stopSYNC(d);
startSYNC(d);
setTimer(100);
// TIM_Cmd(TIM4, ENABLE); //20190408 FreeRTOS CANopen
HAL_TIM_Base_Start_IT(&htim4);
SEGGER_RTT_printf(0, "Master_operational
");
}
メイン関数の初期化時にcanopenネットワークの初期化を呼び出し、
CanopenInit();
この関数はfestivalソースコードで定義されており、以下のように定義されています./**
* @brief CanopenInit
* @param NONE
* @retval NONE
*/
void CanopenInit(void)
{
UNS32 i;
initTimer();
CANOpenMasterObject->canHandle = CAN1;
CANOpenMasterInit(CANOpenMasterObject);
setState(CANOpenMasterObject,Initialisation);
setNodeId (CANOpenMasterObject, 127);
// canInit(CAN1,CAN_BAUD_1M);
canInit(); //20190408 FreeRTOS CANopen
for(i=0; i<65536; i++);
for(i=0; i<65536; i++);
for(i=0; i<65536; i++);
for(i=0; i<65536; i++);
for(i=0; i<65536; i++);
}
ソースコードのcan初期化はボーレートを構成することができ、cubemxでボーレートが構成されているべきであるため、
canInit(CAN1,CAN_BAUD_1M);
関数をログアウトし、canInit();
関数を自主的に実現し、この関数は以下のように定義される.u8 canInit(void)
{
MX_CAN1_Init();
CAN_Filter_Init();
return 0;
}
この関数はcubemxで生成されたcan初期化関数を呼び出し,自分で実現したcanフィルタ初期化関数を加える.
これでcan festival移植が完了し、canopen通信ネットワークホスト機能が実現しました.
小結