文章目录

一、简介二、步骤1. 先编写c语言文件。用CRC8举例。crc8_2f.c crc8_2f.h2. 编译成DLL文件3. 给上位机调用(1)C#(2) 易语言

三、编译成EXE1. 编写一个c文件。 merge_hex.c(例:hex文件合并)2. 编译文件3. 合并脚本.bat

一、简介

在联合开发过程中,用c语言写好功能函数,给其他上位机程序调用。

var code = "635c8ea0-42a5-4ad2-aac1-c1c45d05ea27"

二、步骤

1. 先编写c语言文件。用CRC8举例。crc8_2f.c crc8_2f.h

#include

#include

/* Constant array CRC8 */

static const uint8_t LIB_Crc8Table1[16] = {

0x42u, 0x6du, 0x1cu, 0x33u, 0xfeu, 0xd1u, 0xa0u, 0x8fu,

0x15u, 0x3au, 0x4bu, 0x64u, 0xa9u, 0x86u, 0xf7u, 0xd8u

};

static const uint8_t LIB_Crc8Table2[16] = {

0x42u, 0xecu, 0x31u, 0x9fu, 0xa4u, 0x0au, 0xd7u, 0x79u,

0xa1u, 0x0fu, 0xd2u, 0x7cu, 0x47u, 0xe9u, 0x34u, 0x9au

};

/**

* @brief This function calculates a CRC8 over the data buffer

* @param LIB_TempInputCrc8_cp[in]: pointer to the input data

* @param LIB_TempLengthCrc8_u16[in]: Length of the input data

* @return Calculated CRC8

* @details Local variables

* Loop over all byte

* Execute CRC algorithm

* Return inverted result

* @ReqKey MOD_LIB-64, MOD_LIB-65

*/

uint8_t CRC8Calculation(const uint8_t* data, const uint16_t len) {

/* Local Variables */

uint8_t LIB_TempCrc8_u8 = 0xFFu;

uint16_t LIB_TempIndexCrc8_u16;

/* Loop over all bytes */

for (LIB_TempIndexCrc8_u16 = 0u;

LIB_TempIndexCrc8_u16 < len;

LIB_TempIndexCrc8_u16++) {

/* CRC Algorithm */

LIB_TempCrc8_u8 = data[LIB_TempIndexCrc8_u16] ^ LIB_TempCrc8_u8;

LIB_TempCrc8_u8 = (LIB_Crc8Table1[LIB_TempCrc8_u8 & 0x0Fu]) ^

(LIB_Crc8Table2[LIB_TempCrc8_u8 >> 4u]);

}

return (LIB_TempCrc8_u8 ^ 0xFF);

}

#include

#include

#include

#ifndef CRC8_2F_H_

#define CRC8_2F_H_

uint8_t CRC8Calculation(void* data, uint16_t size);

#endif

2. 编译成DLL文件

cmd 执行下面命令:

gcc -shared crc8_2f.c -o crc8_2f.dll

需要安装gcc编译器mingw32。

3. 给上位机调用

(1)C#

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Runtime.InteropServices;

namespace CallTheDll01

{

class Program

{

// 在此处使用 crc8_2f.dll 文件的绝对路径

[DllImport(@"D:\crc8_2f.dll",CallingConvention=CallingConvention.Cdecl)]

public static extern byte CRC8Calculation(void* data, ushort size);

// 上面已经使用了 crc8_2f.dll 文件的绝对路径,

// 在此处可以只写该 dll文件名,但为了保险起见,还是最好写待调用dll文件的绝对路径名

[DllImport("crc8_2f.dll", EntryPoint = "CRC8Calculation",CallingConvention =CallingConvention.Cdecl)]

public static extern byte CRC8_Cal(void* data, ushort size);

static void Main(string[] args)

{

byte[] data = new byte[] {3, 32, 35, 6, 12, 21, 122};

Console.WriteLine("{0}", CRC8Calculation(data, 7));

Console.WriteLine("{0}", CRC8_Cal(data, 7));

Console.ReadKey();

}

}

(2) 易语言

.版本 2

.DLL命令 read, 整数型, "crc8_2f.dll", "@CRC8Calculation", 公开, @代表使用__stdcall,否则报错-堆栈错误

.参数 buff, 字节集, 传址

.参数 len, 整数型

三、编译成EXE

1. 编写一个c文件。 merge_hex.c(例:hex文件合并)

#include

#include

#include

#include

#include

/**

* @brief 得到文件行

* @param path: 文件路径

* @retval 文件行数(hex文件每行44列)

*/

int GetFileLIine(char* path) {

int i = 0;

// char j = 0;

char str[45];

FILE* fp;

// printf("Path: %s \n",path);

if ((fp = fopen(path, "r")) == NULL)

printf("fail to open the file path:%s! \n", path);

while (fgets(str, 45, fp)) {

i++;

}

fclose(fp);

return i;

}

/**

* @brief 路径处理

* @param ParaPath:

* @param TargetPath: 目标路径

* @param flag: 1表示遇到'\'需要进行增加一个'\'处理, 0表示不需要处理

* @retval

*/

int FileNameHandle(char* ParaPath, char* TargetPath, int flag) {

char* CurrentPath;

int i = 0, j = 0, k = 0;

int PathLevel = 0, PathLast = 0;

// 获取传入的参数路径有多少个上级目录,也就是"..\"的个数

for (i = 0; (ParaPath[i] == '\\') || (ParaPath[i] == '.'); i++) {

if ((ParaPath[i] == '.') && (ParaPath[i - 1] == '.')) {

PathLevel++;

}

}

// printf("ParaPath:%s\n",ParaPath);

// printf("PathLevel:%d i is:%d\n",PathLevel,i);

// 获取当前绝对路径

if ((CurrentPath = getcwd(NULL, 0)) == NULL) {

perror("getcwd error");

}

// printf("CurrentPath: %s\n",CurrentPath);

// 当前绝对路径字符串由后往前遍历,根据上级目录个数PathLevel,去掉多余路径,得到参数路径的绝对路径

for (i = strlen(CurrentPath) - 1; PathLast < PathLevel; i--) {

if (CurrentPath[i] == '\\') {

PathLast++;

}

}

// printf("PathLast:%d i is:%d\n",PathLast,i);

// 将处理后的当前绝对路径,赋值到目标路径的前面

for (j = 0, k = 0; j <= i; j++) {

TargetPath[k++] = CurrentPath[j];

if (flag)

if (CurrentPath[j] == '\\')

TargetPath[k++] = '\\';

}

TargetPath[k] = '\0';

// printf("TargetPath:%s\n",TargetPath);

for (i = 0; ParaPath[i] != '\0'; i++) {

if (ParaPath[i] != '.') {

TargetPath[k++] = ParaPath[i];

if (flag)

if (ParaPath[i] == '\\')

TargetPath[k++] = ParaPath[i];

}

if ((ParaPath[i] == '.') && ((ParaPath[i - 1] != '.') && (ParaPath[i + 1] != '.')))

TargetPath[k++] = ParaPath[i];

}

TargetPath[k] = '\0';

// printf("TargetPath:%s\n",TargetPath);

free(CurrentPath);

return k;

}

int FileHandle(char* path1, char* path2, char* path3, char* path4) {

FILE* fp1;

FILE* fp2;

FILE* fp3;

char str[45];

char* mergeflie;

int i = 0;

int k1 = 0, k2 = 0;

char CurrentPath[2048];

FileNameHandle(path4, CurrentPath, 0);

k1 = GetFileLIine(path1);

k2 = GetFileLIine(path2);

mergeflie = (char*)malloc((k1 + k2) * 45);

mergeflie[0] = '\0';

if ((fp1 = fopen(path1, "r")) == NULL)

printf("fail to open the file path:%s! \n", path1);

for (i = 0; i < k1 - 2; i++) {

fgets(str, 45, fp1);

strcat(mergeflie, str);

}

fclose(fp1);

// printf("Path: %s,line number:%d \n",path1,i);

if ((fp2 = fopen(path2, "r")) == NULL)

printf("fail to open the file path:%s! \n", path2);

// printf("k2-1:%d\n",k2-1);

fgets(str, 45, fp2);

for (i = 0; i < k2 - 1; i++) {

fgets(str, 45, fp2);

strcat(mergeflie, str);

}

fclose(fp2);

i = strlen(mergeflie);

mergeflie[i] = '\n';

if ((fp3 = fopen(path3, "w")) == NULL)

printf("fail to open the file path:%s! \n", path3);

else {

fwrite(mergeflie, strlen(mergeflie), 1, fp3);

printf("creat %s success!\n", CurrentPath); // 打印参数传入的原始路径

}

fclose(fp3);

free(mergeflie);

return 0;

}

int main(int argc, char** argv) {

char path[3][2048];

if (argc < 4) {

printf("error!\n");

printf("参数缺失\n");

return -1;

}

FileNameHandle(argv[1], path[0], 1); // bootloader path

FileNameHandle(argv[2], path[1], 1); // app path

FileNameHandle(argv[3], path[2], 1); // mergeHex path

FileHandle(path[0], path[1], path[2], argv[3]);

return 0;

}

2. 编译文件

gcc merge_hex.c -o mergeHEX2.exe

3. 合并脚本.bat

echo off

mergeHEX2.exe .\BOOT.hex .\MCU.hex .\boot_app.hex

pause

用于合并hex文件的小工具,通过批处理脚本调用传参,在MDK中,可以在魔术棒的User选项卡设置编译后调用批处理脚本,使用起来非常方便.