简易电脑端和单片机进行数据交互

5070 Views

因为单片机和电脑上计算速度和精度的不同,算法在电脑端模拟和移植到单片机内运行的效果并不相同,所以为了准确的验证算法的效果及运行的稳定性,把数据传递到单片机内去运行,运行结果再发送给电脑端是一个不错的验证方式。 该项目采用的是串口传输,其传输的最大速度设置为256000bps,但是该速度对于文件的传输是非常慢的,所以在单片机上测试算法的可行性需要耐心去等待。

设计的通信协议为:

主机从机发送开始信号’S’»>«<中断接收回复’C’,关闭中断发送起始帧»>«<接收正确回复’A’,错误回复’R’发送数据帧»>«<回复’A’ 或 ‘R’等待单片机处理数据处理«<回复数据帧接收正确回复’A’,错误回复’R’»>重复发送,直到完成……最后不够一包数据,标识为END»>«<正确回复’A’,无数据回复发送结束帧»>……接收数据,不回复结束重新打开中断主机基于Labwindows CVI设计的,从机基于STM32F103设计。

项目链接文件

主机的传输格式:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

#ifndef _PROTOCOL_H_

#define _PROTOCOL_H_

#include

#define FRAME_SIZE 512

#define DATA_BLOCK_SIZE (FRAME_SIZE * 2)

#define SIGNAL_START 1

#define SIGNAL_DATA 2

#define SIGNAL_END 3

#define FORMAT_CHAR 1

#define FORMAT_SHORT 2

#define FORMAT_INT 3

#define FORMAT_FLOAT 4

typedef struct

{

uint8_t content_type;

uint8_t frame_index;

uint8_t inv_index;

uint8_t data_format;

uint8_t data_size[2];

uint8_t crc[2];

} FormatTransmit;

typedef struct

{

uint8_t content_type;

uint8_t frame_index;

uint8_t inv_index;

uint8_t data[DATA_BLOCK_SIZE];

uint8_t data_format;

uint8_t data_size[2];

uint8_t crc[2];

} DataTransmit;

int UserProtocol(char *in_file, char *out_file);

void FolderProcess(char *folder_in, char *folder_out);

#endif

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

#include "protocol.h"

#include "crcLib.h"

#include "main.h"

#include "ui_setting.h"

#include "wav_read.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include

extern int panelHandle;

/**

* @brief 计算文件大小

*

* @param fp 文件指针

* @return long 文件大小

*/

long FileSize(FILE *fp)

{

long size = 0;

fseek(fp, 0, SEEK_END);

size = ftell(fp);

fseek(fp, 0, SEEK_SET);

return size;

}

/**

* @brief 判断数据帧的CRC是否正确

*

* @param data 数据帧

* @return int 1-正确,0-错误

*/

int JudgeCRC(DataTransmit *data)

{

uint8_t *in = NULL;

uint16_t crc = 0;

uint8_t crc_h, crc_l;

in = (uint8_t *)data;

crc = crc16_maxim(in, sizeof(DataTransmit) - 2);

crc_h = (uint8_t)(crc >> 8);

crc_l = (uint8_t)(crc & 0xff);

if ((crc_h == data->crc[0]) && (crc_l == data->crc[1]))

{

return 1;

}

return 0;

}

FormatTransmit format = {0}; // 格式帧传输

DataTransmit data = {0}; // 数据帧传输

/**

* @brief 用户通信协议

*

* @param in_file 输入文件

* @param out_file 输出文件

* @return int

*/

int UserProtocol(char *in_file, char *out_file)

{

FILE *fp_in = NULL; // 文件输入指针

FILE *fp_out = NULL; // 文件输出指针

char msg[64] = {0}; // 消息

long file_size = 0; // 文件大小

int send_step = 0; // 发送步骤

int send_new = 0; // 发送新一帧

char byte_value = 0; // 字节数据

int file_read_status = 0; // 文件读取状态

// 这里的数据根据实际修改类型

short *pdata = (short *)data.data;

uint16_t crc = 0; // crc校验值

int data_cnt = 1; // 发送数据计数

int wait_cnt = 0; // 等待计数

WAV_HEAD header = {0}; // wav文件头

int frame_cnt = 0; // 文件帧数

clock_t start_time = 0; // 开始时间

clock_t end_time = 0; // 结束时间

fp_in = fopen(in_file, "rb");

fp_out = fopen(out_file, "wb");

if (!fp_in || !fp_out)

{

sprintf(msg, "Error opening %s or %s\n", fp_in, fp_out);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg);

return 1;

}

memset(msg, 0, sizeof(msg));

file_size = FileSize(fp_in);

sprintf(msg, "File Size is %d\n", file_size);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg);

WAV_AnalyzeHead(fp_in, &header);

/*skip the 44 head*/

fseek(fp_in, WAVE_HEAD_SIZE, SEEK_SET);

fseek(fp_out, WAVE_HEAD_SIZE, SEEK_SET);

while (1)

{

switch (send_step)

{

case 0: // 等待接收端开始接收数据

{

wait_cnt++;

SetCtrlVal(panelHandle, PANEL_TEXTBOX, "等待接收端开始接收\n");

// FlushInQ(com_port);

ComRd(com_port, &byte_value, 1);

if ((byte_value == 'c') || (byte_value == 'C'))

{

wait_cnt = 0;

send_step = 1;

}

if (wait_cnt > 10)

{

SetCtrlVal(panelHandle, PANEL_TEXTBOX, "超时未响应\n");

return (-2);

}

Sleep(50);

break;

}

case 1: // 发送起始帧

{

SetCtrlVal(panelHandle, PANEL_TEXTBOX, "发送起始帧\n");

format.content_type = SIGNAL_START;

format.frame_index = 0x00;

format.inv_index = 0xff;

format.data_format = FORMAT_FLOAT;

format.data_size[0] == 0x00;

format.data_size[1] == 0x00;

crc = crc16_maxim((uint8_t *)&format, sizeof(format) - 2);

format.crc[0] = (uint8_t)(crc >> 8);

format.crc[1] = (uint8_t)(crc & 0xff);

while (GetOutQLen(com_port) > 10)

{

Sleep(50);

}

FlushInQ(com_port);

ComWrt(com_port, (char *)&format, sizeof(FormatTransmit));

SetCtrlVal(panelHandle, PANEL_TEXTBOX, "等待应答起始帧\n");

while (1)

{

wait_cnt++;

ComRd(com_port, &byte_value, 1);

if ((byte_value == 'a') || (byte_value == 'A')) // ACK

{

send_step = 255;

break;

}

else if ((byte_value == 'r') || (byte_value == 'R')) // RESEND

{

break;

}

else

{

if (wait_cnt > 10)

{

return (-3);

}

}

}

if (send_step == 255)

{

SetCtrlVal(panelHandle, PANEL_TEXTBOX, "开始数据发送\n");

send_new = 1;

send_step = 2;

start_time = clock();

}

break;

}

case 2: // 发送数据帧

{

if (send_new) // 读取文件

{

file_read_status = WAV_ReadBuffer(fp_in, pdata, FRAME_SIZE);

long current_position = ftell(fp_in);

Schedule(current_position, file_size);

}

if (file_read_status)

{

frame_cnt++;

data.content_type = SIGNAL_DATA;

data.data_size[0] = FRAME_SIZE / 256;

data.data_size[1] = FRAME_SIZE % 256;

}

else

{

data.content_type = SIGNAL_END;

data.data_size[0] = 0x00;

data.data_size[1] = 0x01;

}

data.frame_index = data_cnt & 0xff;

data.inv_index = (data_cnt ^ 0xff) & 0xff;

// memcpy(data.data, pdata, 1024);

data.data_format = FORMAT_FLOAT;

crc = crc16_maxim((uint8_t *)&data, sizeof(data) - 2);

data.crc[0] = (uint8_t)(crc >> 8);

data.crc[1] = (uint8_t)(crc & 0xff);

while (GetOutQLen(com_port) > 10)

{

Sleep(10);

}

ComWrt(com_port, (char *)&data, sizeof(data));

ComRd(com_port, &byte_value, 1);

if ((byte_value == 'a') || (byte_value == 'A'))

{

if (file_read_status)

{

if (sizeof(data) == ComRd(com_port, (char *)&data, sizeof(data)))

{

if (1 == JudgeCRC(&data))

{

FlushInQ(com_port);

byte_value = 'a';

ComWrt(com_port, &byte_value, 1);

WAV_WriteBuffer(fp_out, pdata, FRAME_SIZE);

send_new = 1;

data_cnt++;

}

else

{

FlushInQ(com_port);

byte_value = 'r';

ComWrt(com_port, &byte_value, 1);

}

}

}

else

{

send_step = 3;

}

}

else if ((byte_value == 'r') || (byte_value == 'R'))

{

send_new = 0;

}

break;

}

case 3: /*第3步,发送结束帧*/

{

memset(&format, 0, sizeof(format));

format.content_type = SIGNAL_END;

format.frame_index = 0xff;

format.inv_index = 0x00;

format.data_format = FORMAT_FLOAT;

crc = crc16_maxim((uint8_t *)&format, sizeof(format) - 2);

format.crc[0] = (uint8_t)(crc >> 8);

format.crc[1] = (uint8_t)(crc & 0xff);

while (GetOutQLen(com_port) > 10)

{

Sleep(50);

}

FlushInQ(com_port);

ComWrt(com_port, (char *)&format, sizeof(FormatTransmit));

header.sub_chunk_size = FRAME_SIZE * 2 * frame_cnt;

header.chunk_size = header.sub_chunk_size + 36;

WAV_WriteHead(fp_out, &header);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, "\n全部发送完成\n");

end_time = clock();

memset(msg, 0, sizeof(msg));

sprintf(msg, "运行时间为 :%.2f秒\n", (float)(end_time - start_time) / CLOCKS_PER_SEC);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg);

send_step = 100;

break;

}

default:

break;

}

if (send_step > 20) /*全部发送完成,结束*/

{

break;

}

}

return 0;

}

#define MAX_NUM 100 /*dir file number*/

#define MAX_CHAR 100 /*max file name length */

char file_in[MAX_NUM][MAX_CHAR] = {0}; /*The specified file within the folder*/

char file_out[MAX_NUM][MAX_CHAR] = {0}; /*The write file within the folder*/

int file_cnt = 0; /*quantity of file*/

/**

* @brief 读取文件夹内所有指定文件

*

* @param folder_in 输入文件夹

* @param folder_out 输出文件夹

* @return int

*/

int CVI_TraverseFolder(char *folder_in, char *folder_out)

{

WIN32_FIND_DATA fileData;

HANDLE hFind;

char path[MAX_PATH] = {0};

strcpy(path, folder_in);

strcat(path, "\\*.wav");

hFind = FindFirstFile(path, &fileData);

if (hFind != INVALID_HANDLE_VALUE)

{

do

{

if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))

{

sprintf(file_in[file_cnt], "%s\\%s", folder_in, fileData.cFileName);

sprintf(file_out[file_cnt], "%s\\%s", folder_out, fileData.cFileName);

file_cnt++;

}

} while (FindNextFile(hFind, &fileData) != 0);

FindClose(hFind);

}

return 0;

}

/**

* @brief 批文件处理

*

* @param folder_in 输入文件夹

* @param folder_out 输出文件夹

*/

void FolderProcess(char *folder_in, char *folder_out)

{

char msg[100] = {0};

sprintf(msg, "输入文件夹为: %s\n", folder_in);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg);

memset(msg, 0, sizeof(msg));

sprintf(msg, "输出文件夹为: %s\n", folder_out);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg);

CVI_TraverseFolder(folder_in, folder_out);

for (int i = 0; i < file_cnt; i++)

{

memset(msg, 0, sizeof(msg));

sprintf(msg, "%s\n%s\n", file_in[i], file_out[i]);

SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg);

SendStartSignal();

UserProtocol(file_in[i], file_out[i]);

Sleep(100);

}

}

从机的传输格式:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#ifndef PROTOCOL_H

#define PROTOCOL_H

#include

#define FRAME_SIZE 512

#define DATA_BLOCK_SIZE (FRAME_SIZE * 2)

#define FRAME_START 1

#define FRAME_DATA 2

#define FRAME_END 3

#define FORMAT_CHAR 1

#define FORMAT_SHORT 2

#define FORMAT_INT 3

#define FORMAT_FLOAT 4

typedef enum

{

SerialOK,

SerialError

} UserStatus;

typedef struct

{

uint8_t content_type;

uint8_t frame_index;

uint8_t inv_index;

uint8_t data_format;

uint8_t data_size[2];

uint8_t crc[2];

} FormatTransmit;

typedef struct

{

uint8_t content_type;

uint8_t frame_index;

uint8_t inv_index;

uint8_t data[DATA_BLOCK_SIZE];

uint8_t data_format;

uint8_t data_size[2];

uint8_t crc[2];

} DataTransmit;

UserStatus RecvStartFrame(void);

UserStatus RecvDataFrame(void);

UserStatus RecvEndFrame(void);

#endif

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

#include "protocol.h"

#include "crcLib.h"

#include "usart.h"

#include

#include

#include

FormatTransmit format = {0};

DataTransmit dSend = {0};

DataTransmit dRecv = {0};

extern int16_t receiveStep;

void RecvDataProcess(DataTransmit *recv, DataTransmit *send);

void CalculateCRC(DataTransmit *data)

{

uint8_t *in = NULL;

uint16_t crc = 0;

in = (uint8_t *)data;

crc = crc16_maxim(in, sizeof(DataTransmit) - 2);

data->crc[0] = (uint8_t)(crc >> 8);

data->crc[1] = (uint8_t)(crc & 0xff);

}

/**

* @brief 判断接收的数据帧是否正确

*

* @param data

* @return UserStatus

*/

UserStatus JudgeDataCRC(DataTransmit *data)

{

uint8_t *in = NULL;

uint16_t crc = 0;

uint8_t crc_h, crc_l;

in = (uint8_t *)data;

crc = crc16_maxim(in, sizeof(DataTransmit) - 2);

crc_h = (uint8_t)(crc >> 8);

crc_l = (uint8_t)(crc & 0xff);

if ((crc_h == data->crc[0]) && (crc_l == data->crc[1]))

{

return SerialOK;

}

return SerialError;

}

UserStatus JudgeFormatCRC(FormatTransmit *data)

{

uint8_t *in = NULL;

uint16_t crc = 0;

uint8_t crc_h, crc_l;

in = (uint8_t *)data;

crc = crc16_maxim(in, sizeof(FormatTransmit) - 2);

crc_h = (uint8_t)(crc >> 8);

crc_l = (uint8_t)(crc & 0xff);

if ((crc_h == data->crc[0]) && (crc_l == data->crc[1]))

{

return SerialOK;

}

return SerialError;

}

UserStatus RecvStartFrame(void)

{

int recvCnt = 0;

//__HAL_UART_FLUSH_DRREGISTER(&huart1);

while (1)

{

HAL_UART_Receive(&huart1, (uint8_t *)&format, 8, 1000);

if ((JudgeFormatCRC(&format) == SerialOK) && (format.content_type == FRAME_START))

{

HAL_UART_Transmit(&huart1, "a", 1, 0xff);

return SerialOK;

}

else

{

HAL_UART_Transmit(&huart1, "r", 1, 0xff);

}

if (recvCnt++ == 5)

{

return SerialError;

}

}

}

UserStatus SendDataFrame(void)

{

uint8_t byte = 0;

HAL_UART_Transmit(&huart1, (uint8_t *)&dSend, sizeof(DataTransmit), 1000);

/*等待ACK响应*/

HAL_UART_Receive(&huart1, (uint8_t *)&byte, 1, 1000);

if (byte == 'a')

{

return SerialOK;

}

else if (byte == 'r')

{

/*清除串口接收*/

__HAL_UART_FLUSH_DRREGISTER(&huart1);

return SerialError;

}

return SerialError;

}

UserStatus RecvDataFrame(void)

{

uint16_t recvCnt = 0;

uint8_t byte = 0;

while (1)

{

if (recvCnt++ == 5)

{

return SerialError;

}

memset(&dRecv, 0, sizeof(DataTransmit));

HAL_UART_Receive(&huart1, (uint8_t *)&dRecv, sizeof(DataTransmit), 1000);

if (SerialOK == JudgeDataCRC(&dRecv))

{

if (dRecv.content_type == FRAME_DATA)

{

HAL_UART_Transmit(&huart1, "a", 1, 0xff);

/*接收到的数据处理*/

// memcpy(&dSend, &dRecv, sizeof(DataTransmit));

RecvDataProcess(&dRecv, &dSend);

CalculateCRC(&dSend);

/*处理结束*/

HAL_UART_Transmit(&huart1, (uint8_t *)&dSend, sizeof(DataTransmit), 1000);

/*等待ACK响应*/

// memset(&dRecv, 0, sizeof(DataTransmit));

HAL_UART_Receive(&huart1, &byte, 1, 1000);

if (byte == 'a')

{

__HAL_UART_FLUSH_DRREGISTER(&huart1);

return SerialOK;

}

else if (byte == 'r')

{

/*清除串口接收*/

__HAL_UART_FLUSH_DRREGISTER(&huart1);

if (SerialError == SendDataFrame())

{

return SerialError;

}

}

}

else if (dRecv.content_type == FRAME_END)

{

/*数据传输结束*/

HAL_UART_Transmit(&huart1, "a", 1, 0xff);

receiveStep = 3;

return SerialOK;

}

}

else

{

HAL_UART_Transmit(&huart1, "r", 1, 0xff);

__HAL_UART_FLUSH_DRREGISTER(&huart1);

}

}

}

UserStatus RecvEndFrame(void)

{

HAL_UART_Receive(&huart1, (uint8_t *)&format, sizeof(format), 1000);

if ((JudgeFormatCRC(&format) == SerialOK) && (format.content_type == FRAME_END))

{

// HAL_UART_Transmit(&huart1, "a", 1, 0xff);

return SerialOK;

}

return SerialError;

}

void RecvDataProcess(DataTransmit *recv, DataTransmit *send)

{

int data_len = 0;

short *in_data = (short *)recv->data;

short *out_data = (short *)send->data;

data_len = recv->data_size[0] * 256 + recv->data_size[1];

for (short i = 0; i < data_len; i++)

{

out_data[i] = in_data[i] / 2;

}

}

从机主函数循环:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

while (g_bReceive)

{

switch (receiveStep)

{

{

case 0:

{

/*中断内进行了主从设备应答,并关闭了中断*/

/*算法数据初始化*/

receiveStep = 1;

break;

}

case 1:

{

if (SerialOK == RecvStartFrame())

{

receiveStep = 2;

}

else

{

g_bReceive = 0;

}

break;

}

case 2:

{

// 接收数据帧

RecvDataFrame();

break;

}

case 3:

{

// 接收结束帧

RecvEndFrame();

__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);

g_bReceive = 0;

receiveStep = 0;

break;

}

default:

{

break;

}

}

}

}

绝对经典钓鱼技巧
说说最好的道术小说《茅山后裔》,为什么多年后还让人念念不忘!