-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcan.c
330 lines (295 loc) · 11.1 KB
/
can.c
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
#include "Allheaderfile.h"
//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元. 范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
//则波特率为:42M/((6+7+1)*6)=500Kbps
//返回值:0,初始化OK;
// 其他,初始化失败;
u8 canbuf[8];//前四个3508电机输出电流值
u8 canbuf_[8];//储存数据帧
u8 canbuf2[8];//后四个3508电机输出电流值
u8 canbuf2_[8];//储存数据帧
u8 flag_full=0;
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN1_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
//使能相关时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
//初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
//引脚复用映射配置
GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode= mode; //模式设置
CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
//配置过滤器
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN1_RX0_INT_ENABLE
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
return 0;
}
/******can2设置*******/
u8 CAN2_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN2_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif
//使能相关时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);//使能CAN2时钟
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, DISABLE);
//初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化PA11,PA12
//引脚复用映射配置
GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_CAN2); //GPIOA11复用为CAN1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_CAN2); //GPIOA12复用为CAN1
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode= mode; //模式设置
CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1
CAN_Init(CAN2, &CAN_InitStructure); // 初始化CAN1
//配置过滤器
CAN_FilterInitStructure.CAN_FilterNumber=14; //过滤器14,can2从14开始
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN2_RX0_INT_ENABLE
CAN_ITConfig(CAN2,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 主优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 次优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
return 0;
}
void set_motor_3508_massage(MOTOR_3508_MSG * motor_msg,u8 * buf)
{
motor_msg->speed=(buf[2]<<8 | buf[3]); //获得转子转速
if(motor_msg->speed>65536/2)//得到反转的速度
motor_msg->speed=-(0XFFFF-motor_msg->speed);
motor_msg->ecd =(buf[0] << 8 |buf[1]);//获得转子机械角度范围是0~8191,对应360度
motor_msg->angle = motor_msg->ecd/8192.0f*360.0f;//得到转子角度
motor_msg->last_ecd = motor_msg->ecd;
}
#if CAN1_RX0_INT_ENABLE //使能RX0中断
//中断服务函数
void CAN1_RX0_IRQHandler(void)
{
// CanRxMsg RxMessage;
if (CAN_GetITStatus(CAN1,CAN_IT_FMP0) != RESET)
{
switch (CAN1_Receive_Msg(canbuf_))
{
case 1:
{
set_motor_3508_massage(&motor_3508.ID1,canbuf_);
break;
}
case 2:
{
set_motor_3508_massage(&motor_3508.ID2,canbuf_);
break;
}
case 3:
{
set_motor_3508_massage(&motor_3508.ID3,canbuf_);
break;
}
case 4:
{
set_motor_3508_massage(&motor_3508.ID4,canbuf_);
break;
}
default:
break;
}
memset(canbuf_,0,sizeof(canbuf_));
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
}
}
#endif
/****************/
//can2中断//
/*************/
#if CAN2_RX0_INT_ENABLE //使能RX0中断
//中断服务函数
void CAN2_RX0_IRQHandler(void)
{
// CanRxMsg RxMessage;
if (CAN_GetITStatus(CAN2,CAN_IT_FMP0) != RESET)
{
switch (CAN2_Receive_Msg(canbuf2_))
{
case 1:
{
set_motor_3508_massage(&motor_3508.ID5,canbuf2_);
break;
}
case 2:
{
set_motor_3508_massage(&motor_3508.ID6,canbuf2_);
break;
}
case 3:
{
set_motor_3508_massage(&motor_3508.ID7,canbuf2_);
break;
}
case 4:
{
set_motor_3508_massage(&motor_3508.ID8,canbuf2_);
break;
}
default:
break;
}
memset(canbuf2_,0,sizeof(canbuf2_));
CAN_ClearITPendingBit(CAN2, CAN_IT_FMP0);
}
}
#endif
//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
//len:数据长度(最大为8)
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
// 其他,失败;
u8 CAN1_Send_Msg(u8* msg,u8 len,u8 expend)
{
u8 mbox;
u16 i=0;
CanTxMsg TxMessage;
TxMessage.StdId=CAN_CHASSIS_ALL_ID; // 标准标识符为0
TxMessage.ExtId=CAN_CHASSIS_ALL_ID; // 设置扩展标示符(29位)
TxMessage.IDE=CAN_ID_STD; // 使用扩展标识符
TxMessage.RTR=CAN_RTR_DATA; // 消息类型为数据帧,一帧8位
TxMessage.DLC=len; // 发送两帧信息
for(i=0;i<len;i++)
TxMessage.Data[i]=msg[i];
mbox= CAN_Transmit(CAN1, &TxMessage);
i=0;
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
if(i>=0XFFF)return 1;
return 0;
}
u8 CAN2_Send_Msg(u8* msg,u8 len) //发送信息给电调ID6
{
u8 mbox;
u16 i=0;
CanTxMsg TxMessage2;
TxMessage2.StdId=CAN_CHASSIS_ALL_ID; // 标准标识符为0
TxMessage2.ExtId=CAN_CHASSIS_ALL_ID; // 设置扩展标示符(29位)
TxMessage2.IDE=CAN_ID_STD; // 使用扩展标识符
TxMessage2.RTR=CAN_RTR_DATA; // 消息类型为数据帧,一帧8位
TxMessage2.DLC=len; // 发送两帧信息
for(i=0;i<len;i++)
TxMessage2.Data[i]=msg[i];
mbox= CAN_Transmit(CAN2, &TxMessage2);
i=0;
while((CAN_TransmitStatus(CAN2, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
if(i>=0XFFF)return 1;
return 0;
}
//can口接收数据查询
//buf:数据缓存区;
//返回值:0,无数据被收到;
// 其他,接收的数据长度;
u8 CAN1_Receive_Msg(u8 *buf)
{
u32 i;
CanRxMsg RxMessage;
if(CAN_MessagePending(CAN1,CAN_FIFO0)==0)
return -1; //没有接收到数据,直接退出
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据
for(i=0;i<RxMessage.DLC;i++)
buf[i]=RxMessage.Data[i];
return RxMessage.StdId-CAN_CHASSIS_ALL_ID;
}
u8 CAN2_Receive_Msg(u8 *buf)
{
u32 i;
CanRxMsg RxMessage2;
if(CAN_MessagePending(CAN2,CAN_FIFO0)==0)return -1; //没有接收到数据,直接退出
CAN_Receive(CAN2, CAN_FIFO0, &RxMessage2);//读取数据
for(i=0;i<RxMessage2.DLC;i++)
buf[i]=RxMessage2.Data[i];
return RxMessage2.StdId-CAN_CHASSIS_ALL_ID;
}
void M3508_ALL_ZERO_SET(void)
{
motor_3508.ID1.POS_ABS=0;
motor_3508.ID2.POS_ABS=0;
motor_3508.ID3.POS_ABS=0;
motor_3508.ID4.POS_ABS=0;
motor_3508.ID5.POS_ABS=0;
motor_3508.ID6.POS_ABS=0;
motor_3508.ID7.POS_ABS=0;
motor_3508.ID8.POS_ABS=0;
Euler.init_pitch=Euler.pitch;
Euler.init_roll=Euler.roll;
}