uavcan学习,libcanard c语言
1、下載源碼
git clone https://github.com/UAVCAN/libcanard.git cd libcanard git submodules update --init --recursive2、自定義消息
??如創(chuàng)建消息文件 232.Rep.uavcan ,放在目錄nhf1中,內(nèi)容:
uint8 vuint32[32] qint13 zzz??進(jìn)入libcanard\dsdl_compiler目錄,調(diào)用生成c代碼指令:
python3 libcanard_dsdlc --outdir <outdir> <dsdl-definition-uavcan-folder>??生成c文件nhf1_Rep.c, Rep.h,后續(xù)使用。
3、消息發(fā)送舉例
#include "uavcan/protocol/NodeStatus.h"/* Reserve memory and struct for messages */ uint8_t packed_uavcan_msg_buf[UAVCAN_PROTOCOL_NODESTATUS_MAX_SIZE]; /* MAX_SIZE comes from module header as pre-calculated */ uavcan_protocol_NodeStatus msg;msg.uptime_sec = getUptime(); msg.health = UAVCAN_PROTOCOL_NODESTATUS_HEALTH_OK; msg.mode = UAVCAN_PROTOCOL_NODESTATUS_MODE_OPERATIONAL; msg.sub_mode = sub_mode; msg.vendor_specific_status_code = vendor_status_code;/* Encode the filled struct into packed_uavcan_msg_buf, ready to be sent */ const uint32_t len_of_packed_msg = uavcan_protocol_NodeStatus_encode(&msg, packed_uavcan_msg_buf);(void) canardBroadcast(&g_canard,UAVCAN_PROTOCOL_NODESTATUS_SIGNATURE,UAVCAN_PROTOCOL_NODESTATUS_ID,&g_bc_node_status_transfer_id,CANARD_TRANSFER_PRIORITY_MEDIUM,packed_uavcan_msg_buf,len_of_packed_msg);4、消息解析舉例
/* include header */ #include "uavcan/protocol/param/GetSet.h"#define GETSETREQ_NAME_MAX_SIZE 96 // max size needed for the dynamic arrays /* Reserve some memory for the dynamic arrays from the stack */ uint8_t buff[GETSETREQ_NAME_MAX_SIZE]; uint8_t* dyn_buf_ptr = buff;/* Reserve struct */ uavcan_protocol_param_GetSetRequest get_set_req;/* NOTE get_set_req struct will be cleared in the Decode function first */ (void) uavcan_protocol_param_GetSetRequest_decode(transfer,(uint16_t)transfer->payload_len,&get_set_req,&dyn_buf_ptr);/* Now the struct get_set_req "object" is ready to be used */5、代碼范例學(xué)習(xí)
??libcanard\tests\Demo.c
??涉及文件 :
????canard.c
????canard.h
????canard_internals.h
canard:can庫實(shí)例化
onTransferReceived:CAN接收的消息處理函數(shù)
shouldAcceptTransfer:CAN接收的消息是否要處理函數(shù),此函數(shù)決定上面函數(shù)執(zhí)行
UAVCAN庫與底層CAN驅(qū)動(dòng)發(fā)送與接收處理
/* CAN發(fā)送與接收處理含稅 */ static void processTxRxOnce(SocketCANInstance* socketcan, int32_t timeout_msec) {// Transmitting/* 將CAN庫中緩存的消息全部發(fā)送到CAN到驅(qū)動(dòng)上 */for (const CanardCANFrame* txf = NULL; (txf = canardPeekTxQueue(&canard)) != NULL;){/* 發(fā)送一包數(shù)據(jù),會(huì)調(diào)用底層CAN接口 */const int16_t tx_res = socketcanTransmit(socketcan, txf, 0);if (tx_res < 0) // Failure - drop the frame and report{canardPopTxQueue(&canard);(void)fprintf(stderr, "Transmit error %d, frame dropped, errno '%s'\n", tx_res, strerror(errno));}else if (tx_res > 0) // Success - just drop the frame{/* 釋放CAN庫中申請(qǐng)的緩存 */canardPopTxQueue(&canard);}else // Timeout - just exit and try again later{break;}}// ReceivingCanardCANFrame rx_frame;const uint64_t timestamp = getMonotonicTimestampUSec();/* 從底層CAN驅(qū)動(dòng)中接收的數(shù)據(jù)取出來進(jìn)行解析 */const int16_t rx_res = socketcanReceive(socketcan, &rx_frame, timeout_msec);if (rx_res < 0) // Failure - report{(void)fprintf(stderr, "Receive error %d, errno '%s'\n", rx_res, strerror(errno));}else if (rx_res > 0) // Success - process the frame{/* 調(diào)用CAN庫進(jìn)行數(shù)據(jù)解析 */canardHandleRxFrame(&canard, &rx_frame, timestamp);}else{; // Timeout - nothing to do} }CAN發(fā)送內(nèi)容到UAVCAN庫
/*** This function is called at 1 Hz rate from the main loop.*/ static void process1HzTasks(uint64_t timestamp_usec) {/** Purging transfers that are no longer transmitted. This will occasionally free up some memory.*/canardCleanupStaleTransfers(&canard, timestamp_usec);/** Printing the memory usage statistics.*/{const CanardPoolAllocatorStatistics stats = canardGetPoolAllocatorStatistics(&canard);const uint16_t peak_percent = (uint16_t)(100U * stats.peak_usage_blocks / stats.capacity_blocks);printf("Memory pool stats: capacity %u blocks, usage %u blocks, peak usage %u blocks (%u%%)\n",stats.capacity_blocks, stats.current_usage_blocks, stats.peak_usage_blocks, peak_percent);/** The recommended way to establish the minimal size of the memory pool is to stress-test the application and* record the worst case memory usage.*/if (peak_percent > 70){puts("WARNING: ENLARGE MEMORY POOL");}}/** Transmitting the node status message periodically.*/{uint8_t buffer[UAVCAN_NODE_STATUS_MESSAGE_SIZE];makeNodeStatusMessage(buffer);static uint8_t transfer_id; // Note that the transfer ID variable MUST BE STATIC (or heap-allocated)!/* 數(shù)據(jù)廣播到UAVCAN網(wǎng)絡(luò) */const int16_t bc_res = canardBroadcast(&canard,UAVCAN_NODE_STATUS_DATA_TYPE_SIGNATURE,UAVCAN_NODE_STATUS_DATA_TYPE_ID,&transfer_id,CANARD_TRANSFER_PRIORITY_LOW,buffer,UAVCAN_NODE_STATUS_MESSAGE_SIZE);if (bc_res <= 0){(void)fprintf(stderr, "Could not broadcast node status; error %d\n", bc_res);}}node_mode = UAVCAN_NODE_MODE_OPERATIONAL; }UAVCAN庫接收到的消息進(jìn)行應(yīng)答或者decode數(shù)據(jù)
/*** This callback is invoked by the library when a new message or request or response is received.*/ static void onTransferReceived(CanardInstance* ins,CanardRxTransfer* transfer) {if ((transfer->transfer_type == CanardTransferTypeRequest) &&(transfer->data_type_id == UAVCAN_GET_NODE_INFO_DATA_TYPE_ID)){printf("GetNodeInfo request from %d\n", transfer->source_node_id);uint8_t buffer[UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE];memset(buffer, 0, UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE);// NodeStatusmakeNodeStatusMessage(buffer);// SoftwareVersionbuffer[7] = APP_VERSION_MAJOR;buffer[8] = APP_VERSION_MINOR;buffer[9] = 1; // Optional field flags, VCS commit is setuint32_t u32 = GIT_HASH;canardEncodeScalar(buffer, 80, 32, &u32);// Image CRC skipped// HardwareVersion// Major skipped// Minor skippedreadUniqueID(&buffer[24]);// Certificate of authenticity skipped// Nameconst size_t name_len = strlen(APP_NODE_NAME);memcpy(&buffer[41], APP_NODE_NAME, name_len);const size_t total_size = 41 + name_len;/** Transmitting; in this case we don't have to release the payload because it's empty anyway.*/const int16_t resp_res = canardRequestOrRespond(ins,transfer->source_node_id,UAVCAN_GET_NODE_INFO_DATA_TYPE_SIGNATURE,UAVCAN_GET_NODE_INFO_DATA_TYPE_ID,&transfer->transfer_id,transfer->priority,CanardResponse,&buffer[0],(uint16_t)total_size);if (resp_res <= 0){(void)fprintf(stderr, "Could not respond to GetNodeInfo; error %d\n", resp_res);}} }UAVCAN庫對(duì)接收的消息是否需要進(jìn)行處理
/*** This callback is invoked by the library when it detects beginning of a new transfer on the bus that can be received* by the local node.* If the callback returns true, the library will receive the transfer.* If the callback returns false, the library will ignore the transfer.* All transfers that are addressed to other nodes are always ignored.*/ static bool shouldAcceptTransfer(const CanardInstance* ins,uint64_t* out_data_type_signature,uint16_t data_type_id,CanardTransferType transfer_type,uint8_t source_node_id) {(void)source_node_id;if (canardGetLocalNodeID(ins) == CANARD_BROADCAST_NODE_ID){/** If we're in the process of allocation of dynamic node ID, accept only relevant transfers.*/if ((transfer_type == CanardTransferTypeBroadcast) &&(data_type_id == UAVCAN_NODE_ID_ALLOCATION_DATA_TYPE_ID)){*out_data_type_signature = UAVCAN_NODE_ID_ALLOCATION_DATA_TYPE_SIGNATURE;return true;}}else{if ((transfer_type == CanardTransferTypeRequest) &&(data_type_id == UAVCAN_GET_NODE_INFO_DATA_TYPE_ID)){*out_data_type_signature = UAVCAN_GET_NODE_INFO_DATA_TYPE_SIGNATURE;return true;}}return false; }6、總之
?? processTxRxOnce()會(huì)將UAVCAN庫中緩存的消息通過底層CAN接口發(fā)送出去,同時(shí)會(huì)從底層CAN接口取出數(shù)據(jù),放到 canardHandleRxFrame()進(jìn)行數(shù)據(jù)解析,然后會(huì)通過 shouldAcceptTransfer()判斷該消息是否需要,若需要?jiǎng)t onTransferReceived()進(jìn)行decode,根據(jù)消息類型ID調(diào)用對(duì)應(yīng)的自定義decode函數(shù)進(jìn)行數(shù)據(jù)映射。
?? canardBroadcast()會(huì)將數(shù)據(jù)廣播到UAVCAN庫中,進(jìn)行緩存,再通過 processTxRxOnce()進(jìn)行全部發(fā)出,如此循環(huán)。
參考:https://github.com/UAVCAN/libcanard/tree/master
總結(jié)
以上是生活随笔為你收集整理的uavcan学习,libcanard c语言的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: winform菜单栏、快捷菜单、右键弹出
- 下一篇: 随机数字生成器(RNG)和Hash函数组