在联合开发过程中,用c语言写好功能函数,给其他上位机程序调用。
#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
cmd 执行下面命令:
gcc -shared crc8_2f.c -o crc8_2f.dll
需要安装gcc编译器mingw32。
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
.DLL命令 read, 整数型, "crc8_2f.dll", "@CRC8Calculation", 公开, @代表使用__stdcall,否则报错-堆栈错误
.参数 buff, 字节集, 传址
.参数 len, 整数型
#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;
}
gcc merge_hex.c -o mergeHEX2.exe
echo off
mergeHEX2.exe .\BOOT.hex .\MCU.hex .\boot_app.hex
pause
用于合并hex文件的小工具,通过批处理脚本调用传参,在MDK中,可以在魔术棒的User选项卡设置编译后调用批处理脚本,使用起来非常方便.