JZ_uart.c
7.5 KB
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
/* Includes----------------------------------------------------*/
#include "JZ_uart.h"
#include "JZ_beurteilten.h"
/* Private constants-------------------------------------------*/
/* Private types-----------------------------------------------*/
/* Private values----------------------------------------------*/
JzSerData *ser;
pthread_mutex_t mutex;//互斥锁
/* Private functions declaration ---------------------------------------------*/
/* Exported functions definition ---------------------------------------------*/
/************************************
*串口初始化
*函数名:JzUartSet
*函数参数:
@path:串口设备路径
@bitRate:串口波特率
*返回值:成功返回 0 错误返回-1
*函数作者:wzy
*************************************/
int JzUartInit(const char *path,int bitRate)
{
//串口结构体申请内存
ser = (JzSerData *)malloc(sizeof(JzSerData));
if(ser == NULL)
{
return -1;
}
ser->serFd = JzUartSet(path,bitRate);//设置串口参数
//ser->dataBuf,0,
memset(ser->dataBuf,0,sizeof(ser->dataBuf));
ser->dataLen =0;
//初始化互斥锁
pthread_mutex_init(&mutex,NULL);
//创建串口接收线程
pthread_t thread;
pthread_attr_t task_attr;
pthread_attr_init(&task_attr); //初始化线程属性
pthread_attr_setdetachstate(&task_attr, PTHREAD_CREATE_DETACHED); //设置线程分离属性
// 创建线程
int result = pthread_create(&thread, &task_attr, Recv_Task, (void *)(intptr_t)ser->serFd);
if (result != 0) {
printf("线程创建失败\n");
return -1;
}
return 0;
}
/************************************
*串口设置
*函数名:JzUartSet
*函数参数: @path:串口设备路径
@bitRate:串口波特率
*返回值:
成功返回 文件标识符 错误返回-1
*函数作者:wzy
*************************************/
int JzUartSet(const char *path,int bitRate)
{
/* 进行串口参数设置 */
termios_t *ter_s = malloc(sizeof(*ter_s));
int serport1fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY); // 不成为控制终端程序,不受其他程序输出输出影响
if (serport1fd < 0)
{
printf("%s open faild\r\n", path);
return -1;
}
bzero(ter_s, sizeof(*ter_s));
ter_s->c_cflag |= CLOCAL | CREAD; // 激活本地连接与接受使能
ter_s->c_cflag &= ~CSIZE; // 失能数据位屏蔽
ter_s->c_cflag |= CS8; // 8位数据位
ter_s->c_cflag &= ~CSTOPB; // 1位停止位
ter_s->c_cflag &= ~PARENB; // 无校验位
ter_s->c_cc[VTIME] = 0;
ter_s->c_cc[VMIN] = 0;
/*1 VMIN> 0 && VTIME> 0
VMIN为最少读取的字符数,当读取到一个字符后,会启动一个定时器,在定时器超时事前,如果已经读取到了VMIN个字符,则read返回VMIN个字符。如果在接收到VMIN个字符之前,定时器已经超时,则read返回已读取到的字符,注意这个定时器会在每次读取到一个字符后重新启用,即重新开始计时,而且是读取到第一个字节后才启用,也就是说超时的情况下,至少读取到一个字节数据。
2 VMIN > 0 && VTIME== 0
在只有读取到VMIN个字符时,read才返回,可能造成read被永久阻塞。
3 VMIN == 0 && VTIME> 0
和第一种情况稍有不同,在接收到一个字节时或者定时器超时时,read返回。如果是超时这种情况,read返回值是0。
4 VMIN == 0 && VTIME== 0
这种情况下read总是立即就返回,即不会被阻塞。----by 解释粘贴自博客园
*/
//3、设置比特率
switch (bitRate)
{
case 115200:
cfsetispeed(ter_s, B115200);// 设置输入波特率
cfsetospeed(ter_s, B115200);// 设置输出波特率
break;
case 230400:
cfsetispeed(ter_s, B230400);
cfsetospeed(ter_s, B230400);
break;
case 460800:
cfsetispeed(ter_s, B460800);
cfsetospeed(ter_s, B460800);
break;
case 921600:
cfsetispeed(ter_s, B921600);
cfsetospeed(ter_s, B921600);
break;
case 1000000:
cfsetispeed(ter_s, B1000000);
cfsetospeed(ter_s, B1000000);
break;
default:
printf("bitRate error\n");
return -1;
break;
}
tcflush(serport1fd, TCIFLUSH); // 刷清未处理的输入和/或输出
if (tcsetattr(serport1fd, TCSANOW, ter_s) != 0)
{
printf("com set error!\r\n");
}
return serport1fd;
}
/************************************
串口发送任务函数
*************************************/
static void *send_task(void *arg)
{
pthread_mutex_lock(&mutex);
JzSerData * sendser = (JzSerData *)arg;
int ret = write(ser->serFd, ser->dataBuf,ser->dataLen);
if (ret <= 0)//错误处理
{
printf("send error!\r\n");
}
pthread_mutex_unlock(&mutex);//释放锁
// tcflush(ser->serFd, TCOFLUSH);//清除输出缓冲区
}
// int uart_send(uint8_t *dataBuf,int dataLen)
// {
// //pthread_mutex_lock(&mutex);//获取锁
// int ret = write(ser->serFd, dataBuf,dataLen);
// if (ret <= 0)//错误处理
// {
// printf("send error!\r\n");
// return -1;
// }
// // pthread_mutex_unlock(&mutex);//释放锁
// tcflush(ser->serFd, TCOFLUSH);//清除输出缓冲区
// }
/************************************
*串口发送函数
*函数名:uart_send
*函数参数:
@dataBuf:发送的数据
@dataLen:发送数据长度
*返回值:无
*函数作者:wzy
*************************************/
int uart_send(uint8_t *dataBuf,int dataLen)
{
pthread_t thread;
pthread_attr_t task_attr;
pthread_attr_init(&task_attr); //初始化线程属性
pthread_attr_setdetachstate(&task_attr, PTHREAD_CREATE_DETACHED); //设置线程分离属性
memcpy(ser->dataBuf,dataBuf,dataLen);
ser->dataLen = dataLen;
// for(int i=0;i<dataLen;i++)
// {
// printf("%02x ",dataBuf[i]);
// }
// printf("\n");
// 创建线程
int result = pthread_create(&thread, &task_attr, send_task,(void *)ser);
if (result != 0) {
printf("线程创建失败\n");
return -1;
}
return 0;
}
/************************************
串口接收任务函数
*************************************/
static void *Recv_Task(void *arg)
{
int ret = 0;
char recvBuf[256];
char frames[4][32];
int index = 0;
int currentFrame = 0;
int serFd = (int)(intptr_t)arg;
while (1)
{
pthread_mutex_lock(&mutex);//获取锁
ret = read(serFd,recvBuf, 256);
pthread_mutex_unlock(&mutex);//释放锁
if (ret > 0)
{ //分开数据帧
for(int j=0;j<ret;j++)
{
frames[currentFrame][index++] = recvBuf[j];
if(recvBuf[j-1] == 0x00 && recvBuf[j] == 0x23)
{
Received_Content_Determinatio(frames[currentFrame],index);//判断内容
currentFrame++;//下一帧
index = 0;
}
}
memset(recvBuf, '\0', 256);//清空缓冲区
memset(frames, '\0', 128);
// tcflush(serFd, TCIFLUSH);//清除输入缓冲区
}
currentFrame = 0;
usleep(100);
}
}