328 lines
10 KiB
C
328 lines
10 KiB
C
/*!
|
|
Copyright 2017 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
\file v_CANtoRS.c
|
|
\brief Ïðåîáðàçîâàòåëü ïîñûëîê CAN â RS è îáðàòíî. Ðàáîòàåò
|
|
ñîâìåñòíî ñ äðàéâåðîì CANOpen
|
|
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
|
|
\version v 2.0 25/03/2016
|
|
|
|
\addtogroup v_CANtoRS
|
|
@{
|
|
*/
|
|
#include "DSP.h"
|
|
#include "main.h"
|
|
|
|
|
|
|
|
//! \memberof TCANtoRS
|
|
void CANtoRS_init(TCANtoRS *p) {
|
|
|
|
GPIOB->ALTFUNCSET = (1 << 8) + (1 << 9);
|
|
GPIOB->DENSET = (1 << 8) + (1 << 9);
|
|
|
|
p->UART=UART1;//Èñïîëüçóåìûé â äðàéâåðå íîìåð UART (0, 1)
|
|
|
|
p->UART->CR_bit.UARTEN = 1; // Ðàçðåøèòü ðàáîòó UART
|
|
|
|
// Íàñòðîéêà ÷àñòîòû â äâóõ ðåãèñòðàõ:
|
|
// çàäàíèå äåëèòåëÿ ÷àñòîòû äëÿ ïîëó÷åíèÿ BaudRate
|
|
// Ò.ê. áëîê UART òàêòèðóåòñÿ ñ ÷àñòîòîé 25 ÌÃö (òàê íàñòðîåíî â èíèòå ìèêðîêîíòðîëëåðà),
|
|
// òî äëÿ ïîëó÷åíèÿ ÷àñòîòû 57600 áèò/ñ íåîáõîäèì
|
|
// äåëèòåëü 25000000 / (16 * 57600) = 27,126736111111111111111111111111
|
|
// Öåëàÿ ÷àñòü I = 27
|
|
// Äðîáíàÿ ÷àñòü F = (int)( 0.126736111*64 + 0.5 ) = 8
|
|
// Ôîðìóëû ñì. â äîêóìåíòàöèè
|
|
p->UART->IBRD_bit.DIVINT= 27;
|
|
p->UART->FBRD_bit.DIVFRAC = 8;
|
|
|
|
|
|
p->UART->LCRH_bit.SPS = 0; // Íåò ïðîâåðêè ÷åòíîñòè
|
|
p->UART->LCRH_bit.WLEN = 3; // Äëèíà ïîñûëêè 8 áèò
|
|
p->UART->LCRH_bit.FEN = 1; // Èñïîëüçîâàòü FIFO
|
|
p->UART->CR_bit.TXE = 1; // Ðàçðåøèòü ïðè¸ì
|
|
p->UART->CR_bit.RXE = 1; // Ðàçðåøèòü ïåðåäà÷ó
|
|
p->UART->LCRH_bit.STP2 = 0; // 1 ñòîï-áèò
|
|
|
|
p->CounterWrongCRC=0;
|
|
p->CounterRes=0;
|
|
p->CounterSended=0;
|
|
p->PacketInWait=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Èç çàäàííîãî äëÿ ïåðåäà÷è ìàññèâà ôóíêöèÿ ôîðìèðóåò
|
|
//!API ïàêåò, à çàòåì âûçûâàåò ôóíêöèþ
|
|
//!ïîáàéòîâîé îòïðàâêè
|
|
|
|
//! \memberof TCANtoRS
|
|
Uint16 CANtoRS_SendP(Uint16* Data, int16 len, TCANtoRS *p) {
|
|
volatile int16 i;
|
|
Uint16 MyCRC;
|
|
p->buf_out[0]=0x7E;
|
|
for (i=0;i<len;i++)
|
|
p->buf_out[i+1]=Data[i];
|
|
MyCRC=CANtoRS_C_CRC(p,Data,len);
|
|
p->buf_out[len+1]=MyCRC & 0xFF;//ïåðâûé áàéò
|
|
p->buf_out[len+2]=(MyCRC>>8) & 0xFF;//âòîðîé áàéò
|
|
p->all_len=1+len+2;//ïîëíàÿ äëèíà=ñèãíàòóðà+äàííûå + êîíòðîëüíàÿ ñóììà
|
|
|
|
i = 0;
|
|
// Åñëè áóôåð TX íå çàïîëíåí, òî îòïðàâëÿåì âñå áàéòû èç áóôåðà
|
|
while ((p->UART->FR_bit.TXFF != 1) && (i < p->all_len)){
|
|
p->UART->DR = p->buf_out[i];
|
|
i++;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
#define CRC_MAGIC_NUMBER 0xA001
|
|
//! Ôóíêöèÿ ñ÷èòàåò êîíòðîëüíóþ ñóììó ïàêåòà
|
|
//! è ñðàâíèâàåò ñ ïðèíÿòîé. Åñëè âñå âåðíî, òî âîçâðàùàåò 1
|
|
//! \memberof TCANtoRS
|
|
|
|
Uint16 CANtoRS_C_CRC(TCANtoRS *p,Uint16 *Data,Uint16 len) { //ïðîâåðêà êîíòðîëüíîé ñóììû ïðèíÿòîãî API ïàêåòà
|
|
int16 i,j;
|
|
Uint16 MyCalcCRC=0xFFFF;
|
|
|
|
for (j=0;j<len;j++) {
|
|
MyCalcCRC=MyCalcCRC^(Data[j++]&0xFF);
|
|
for (i=0; i<16; i++)
|
|
if (MyCalcCRC&0x01) {
|
|
MyCalcCRC=(MyCalcCRC>>1);
|
|
MyCalcCRC=MyCalcCRC^CRC_MAGIC_NUMBER;
|
|
} else
|
|
MyCalcCRC=(MyCalcCRC>>1);
|
|
}
|
|
|
|
return MyCalcCRC;
|
|
}
|
|
|
|
|
|
|
|
/*! Ôóíêöèÿ âûçûâàåòñÿ, êîãäà ïðèøëè êàêèå-òî äàííûå,
|
|
è îáðàáàòûâàåò èõ êàê ïåðåäàííûé CAN ïàêåò. Âûäåëÿåò
|
|
èäåíòèôèêàòîð, äëèíó è ïðî÷åå. Ðåç-ò ïîìåùàåò â ñòðóêòóðó
|
|
p->MSG */
|
|
//! \memberof TCANtoRS
|
|
void CANtoRS_Analysis(TCANtoRS *p) {
|
|
int16 i,j;
|
|
//ïîñûëêà äàííûõ íà÷èíàåòñÿ ñ 12ãî áàéòà,
|
|
//äî ýòîãî ñëóæåáíàÿ èíôîðìàöèÿ API ïàêåòà
|
|
p->MSG.id=0;
|
|
p->MSG.id=(p->ReadPackData[0] & 7)<<8; //íèæíèå 3 áèòà ñäâèãàåì íàâåðõ;
|
|
p->MSG.id|=p->ReadPackData[1];
|
|
p->MSG.dlc=(p->ReadPackData[0]>>4) & 0xF; //âåðõíèå 4 áèòà ñäâèãàåì âíèç; äëèíà ïîñûëêè
|
|
for (i=2,j=0;i<CANTORS_READ_DATA_MAX_LEN;i++,j++)
|
|
p->MSG.data[j]=p->ReadPackData[i];
|
|
p->callback_go=1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*! Ïîáàéòîâûé îáðàáîò÷èê ïðèõîäÿùèõ ïî SCI äàííûõ.
|
|
Ðàáîòàåò ïî ïðèíöèïó äèñêðåòíîãî àâòîìàòà è ïûòàåòñÿ
|
|
íàéòè â ïîñûëêå API ïàêåò. Ñíà÷àëà æäåò çàäàííóþ ñèãíàòóðó,
|
|
ïîòîì äëèíó è ò.ï. Â êîíöå ïðîâåðÿåò êîíòðîëüíóþ ñóììó è
|
|
âûçûâàåò äàëüíåéøèå îáðàáîò÷èêè */
|
|
//! \memberof TCANtoRS
|
|
|
|
void CANtoRS_Receive(TCANtoRS *p) {
|
|
Uint16 MyReadCRC_u16;
|
|
Uint16 MyCalcCRC;
|
|
Uint32 temp_byte;
|
|
Uint16 repeat;
|
|
for (repeat=0;repeat<7; repeat++) {//îáðàáîòêà íå áîëåå n áàéò çà îäèí âõîä â ôóíêöèþ
|
|
|
|
switch (p->APIpacketMode) {
|
|
|
|
case 0: { //îæèäàíèå ñèãíàòóðû
|
|
|
|
|
|
if (p->UART->FR_bit.RXFE)
|
|
return;
|
|
temp_byte = p->UART->DR_bit.DATA;
|
|
if (temp_byte!=0x7e) {
|
|
p->MessDrop3++;
|
|
return;
|
|
}
|
|
p->ReadPackDataCounter=0;//ñ÷åò÷èê äàííûõ
|
|
p->APIpacketMode=1; //ñèãðíàòóðà íàéäåíà, ðåæèì ïðèåìà äàííûõ
|
|
break;
|
|
};
|
|
case 1: { //îæèäàíèå äàííûõ(ïîëåçíàÿ íàãðóçêà) ïàêåòà
|
|
//âñå ïîñëåäóþùèå áàéòû ñêëàäûâàåì â API áóôåð
|
|
|
|
if (p->UART->FR_bit.RXFE)
|
|
return;
|
|
temp_byte = p->UART->DR_bit.DATA;
|
|
p->ReadPackData[p->ReadPackDataCounter++]=temp_byte;
|
|
if (p->ReadPackDataCounter>=CANTORS_READ_DATA_MAX_LEN) {
|
|
p->ReadPackDataCounter=0;//ñ÷åò÷èê äàííûõ
|
|
p->ReadCRCCounter=0;//ñ÷åò÷èê êîíòðîëüíîé ñóììû
|
|
p->APIpacketMode=2; //äàííûå ïðèíÿòû, ðåæèì ïðèåìà è ïðîâåðñè CRC
|
|
}
|
|
break;
|
|
};
|
|
|
|
case 2: { //îæèäàíèå CRC
|
|
//âñå ïîñëåäóþùèå áàéòû ñêëàäûâàåì â CRC áóôåð
|
|
|
|
if (p->UART->FR_bit.RXFE)
|
|
return;
|
|
temp_byte = p->UART->DR_bit.DATA;
|
|
p->ReadCRC[p->ReadCRCCounter++]=temp_byte;
|
|
if (p->ReadCRCCounter>=2) {
|
|
p->ReadCRCCounter=0;//ñ÷åò÷èê êîíòðîëüíîé ñóììû
|
|
MyReadCRC_u16=(p->ReadCRC[0]&0xFF)+((p->ReadCRC[1]<<8)&0xFF00);//çàïàêîâûâàåì äâóõáàéòîâóþ CRC â îäíó ïåðåìåííóþ
|
|
MyCalcCRC=CANtoRS_C_CRC(p,(Uint16 *)p->ReadPackData,CANTORS_READ_DATA_MAX_LEN);
|
|
if (MyCalcCRC!=MyReadCRC_u16) {
|
|
//îøèáêà!
|
|
p->CounterWrongCRC++;
|
|
p->APIpacketMode=0;
|
|
break;
|
|
}//êîíòðîëüíàÿ ñóììà ïðèíÿòà è âåðíà
|
|
|
|
CANtoRS_Analysis(p);
|
|
if (p->callback_go) { //åñëè âûñòàâëåí ôëàã, âûçîâ callback
|
|
p->callback_go=0;
|
|
p->APIpacketMode=3; //îáðàáîòêà callback
|
|
}
|
|
else
|
|
p->APIpacketMode=0;
|
|
return;
|
|
}
|
|
break;
|
|
};
|
|
case 3: { //îáðàáîòêà callback
|
|
p->CounterRes++;
|
|
p->callback(&co1_vars, (TZCanMsg*)&(p->MSG));
|
|
p->APIpacketMode=0;
|
|
break;
|
|
};
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*! Äîëæíà âûçûâàòüñÿ êàæäóþ ñåêóíäó è îòñûëàåò
|
|
CAN ïàêåòû HeartBeat. Åñëè îòîñëàòü íå âûõîäèò (ïåðåäà÷à çàíÿòà),
|
|
òî ñîêðàùàåò ïîñëåäóþùèé òàéìàóò è, íåìíîãî îáîæäàâ, ïûòàåòñÿ
|
|
îòïðàâèòü çàíîâî */
|
|
//! \memberof TCANtoRS
|
|
void CANtoRS_HeartBeat(TCANtoRS *p) {
|
|
TZCanMsg MSG;
|
|
int16 i;
|
|
MSG.id=0xE<<7;//heartbeat
|
|
MSG.id|=*p->nodeID;//íîìåð óçëà
|
|
MSG.dlc=1;//äëèíà
|
|
for (i=0;i<8;MSG.data[i++]=0);//î÷èñòêà
|
|
MSG.data[0]=5;//äàííûå heartbeat
|
|
if (!CANtoRS_Write(&MSG,p)) { //åñëè íå ïîëó÷èëîñü îòïðàâèòü
|
|
p->HeartCounter=(CANTORS_HEART_COUNTER_MAX-3); //âñêîðå ïðîáóåì ñäåëàòü ýòî åùå ðàç
|
|
p->HeartBeatGo=1;//è åñëè áóäåò ñîáûòèå íà îòïðàâêó SDO, íî áóäåò çíàòü, ÷òî íàäî ïðîïóñòèòü
|
|
} else {
|
|
p->HeartBeatGo=0;
|
|
}
|
|
}
|
|
|
|
|
|
//! \memberof TCANtoRS
|
|
Uint16 CANtoRS_WriteHelper(TZCanMsg* MSG,TCANtoRS *p) {
|
|
if (p->HeartBeatGo) { //õî÷åò îòïðàâèòüñÿ HeartBeat
|
|
CANtoRS_HeartBeat(p);
|
|
p->MessDrop1++;
|
|
return 0;//ñîîáùåíèå òåðÿåì...
|
|
}
|
|
if (CANtoRS_Write(MSG,p))
|
|
p->CounterSended++;
|
|
else {
|
|
p->MessDrop2++;
|
|
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*! Èç ñòðóêòóðû CAN ïàêåòà ôîðìèðóåò ìàññèâ-ïîñûëêó,
|
|
ãäå âíà÷àëå 4 áèòà - äëèíà, ïîòîì 1 áèò ïðîïóñê è 11 èäåíòèôèêàòîð.
|
|
Äàëåå íåïîñðåäñòâåííî äàííûå. Ïîñëå êîíñòðóèðîâàíèÿ ïîñûëêà îòïðàâëÿåòñÿ*/
|
|
//! \memberof TCANtoRS
|
|
Uint16 CANtoRS_Write(TZCanMsg* MSG,TCANtoRS *p) {
|
|
if (!p->PacketInWait) { //íåò ïàêåòà â áóôåðå
|
|
//êîïèðóåì âî âðåìåííûé áóôåð
|
|
p->bufMSG=*MSG;
|
|
p->PacketInWait=1;//ôëàã, ÷òî â áóôåðå ÷òî-òî åñòü
|
|
return 1;
|
|
//ñ÷èòàåòñÿ, ÷òî áóôåðà íà 1 ïîçèöèþ äîëæíî õâàòàòü
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
//! \memberof TCANtoRS
|
|
Uint16 CANtoRS_Write_Real(TZCanMsg* MSG,TCANtoRS *p) {
|
|
int16 i;
|
|
|
|
p->TempData[0]=(MSG->dlc & 0xF)<<4;
|
|
p->TempData[0]|=(MSG->id >> 8) & 7;
|
|
p->TempData[1]=MSG->id & 0xFF;
|
|
for (i=0;i<8;i++) p->TempData[i+2]=MSG->data[i];
|
|
CANtoRS_SendP((Uint16*)p->TempData,10,p);
|
|
return 1;
|
|
}
|
|
|
|
/*! Âûçûâàåòñÿ èç ìèëëèñåêóíäíîãî òàéìåðà, îòñ÷èòûâàåò 1 ñåêóíäó
|
|
è âûçûâàåò ôóíêöèþ îòïðàâêè HeartBeat. Çàîäíî ïðîâåðÿåò,
|
|
åñëè â SCI âîçíèêëà êàêàÿ-òî îøèáêà è îí îñòàíîâèëñÿ, ïåðåçàïóñêàåò.
|
|
*/
|
|
|
|
//! \memberof TCANtoRS
|
|
void CANtoRS_calc(TCANtoRS *p) {
|
|
|
|
//åñëè â áóôåðå åñòü ïàêåò, îæèäàþùèé îòïðàâêè è ïåðåäàò÷èê ñâîáîäåí è íå æäåò heartbeat
|
|
if (p->PacketInWait) {
|
|
if (!CANtoRS_Write_Real((TZCanMsg*)&p->bufMSG,p))//îòïðàâèòü íå óäàëîñü?
|
|
p->MessDrop2++;
|
|
p->PacketInWait=0;//î÷èùàåì áóôåð
|
|
}
|
|
else{//åñëè ïàêåòà íà îòïðàâê íåò, îáðàáàòûâàåòñÿ âñ¸ îñòàëüíîå. Ìîæíî áû è îáðàáàòûâàòü ñðàçó, íî íå õâàòàåò ðåñóðñîâ
|
|
CANtoRS_Receive(p);
|
|
p->HeartCounter++; //ñ÷åò÷èê äëÿ HeartBeat
|
|
|
|
//íå ïîðà ëè îòïðàâèòü HeartBeat?
|
|
if (p->HeartCounter>=(CANTORS_HEART_COUNTER_MAX-1)) {
|
|
p->HeartCounter=0;
|
|
CANtoRS_HeartBeat(p);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*@}*/
|