373 lines
12 KiB
C
373 lines
12 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/USB è îáðàòíî. Ðàáîòàåò
|
|
ñîâìåñòíî ñ äðàéâåðîì CANOpen
|
|
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
|
|
\version v 3.0 08/08/2017
|
|
|
|
\addtogroup v_CANtoRS
|
|
@{
|
|
*/
|
|
#include "DSP.h"
|
|
#include "main.h"
|
|
|
|
|
|
void usb_irq_en(void);
|
|
void usb_irq_dis(void);
|
|
//! \memberof TCANtoRS
|
|
void CANtoRS_init(TCANtoRS *p) {
|
|
#ifdef CANTORS_ENA
|
|
p->NT_UART=UART2; //Èñïîëüçóåìûé â äðàéâåðå íîìåð UART (1,2,3)
|
|
p->NT_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->NT_UART->IBRD_bit.DIVINT= 27;
|
|
p->NT_UART->FBRD_bit.DIVFRAC = 8;
|
|
|
|
|
|
|
|
p->NT_UART->LCRH_bit.SPS = 0; // Íåò ïðîâåðêè ÷åòíîñòè
|
|
p->NT_UART->LCRH_bit.WLEN = 3; // Äëèíà ïîñûëêè 8 áèò
|
|
p->NT_UART->LCRH_bit.FEN = 1; // Èñïîëüçîâàòü FIFO
|
|
p->NT_UART->CR_bit.TXE = 1; // Ðàçðåøèòü ïðè¸ì
|
|
p->NT_UART->CR_bit.RXE = 1; // Ðàçðåøèòü ïåðåäà÷ó
|
|
p->NT_UART->LCRH_bit.STP2 = 0; // 1 ñòîï-áèò
|
|
#endif
|
|
|
|
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;
|
|
|
|
#ifdef CANTORS_ENA
|
|
// Åñëè áóôåð TX íå çàïîëíåí, òî îòïðàâëÿåì âñå áàéòû èç áóôåðà
|
|
while ((p->NT_UART->FR_bit.TXFF != 1) && (i < p->all_len)){
|
|
p->NT_UART->DR = p->buf_out[i];
|
|
i++;
|
|
}
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
#define CRC_MAGIC_NUMBER 0xA001
|
|
//! Ôóíêöèÿ ñ÷èòàåò êîíòðîëüíóþ ñóììó ïàêåòà
|
|
//! è ñðàâíèâàåò ñ ïðèíÿòîé. Åñëè âñå âåðíî, òî âîçâðàùàåò 1
|
|
//! \memberof TCANtoRS
|
|
#if defined (__GNUC__)
|
|
__attribute__((section(".fastcode")))
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
/*! Ôóíêöèÿ âûçûâàåòñÿ, êîãäà ïðèøëè êàêèå-òî äàííûå,
|
|
* è ïðîâåðÿåò, ÷òî ýòè äàííûå êîððåêòíû è ìîãóò áûòü îáðàáîòàíû
|
|
* äðàéâåðîì CANopen. Åñëè ýòî òàê - äàííûå îòïðàâëÿþòñÿ íà
|
|
* îáðàáîòêó
|
|
*/
|
|
//! \memberof TCANtoRS
|
|
#if defined (__GNUC__)
|
|
__attribute__((section(".fastcode")))
|
|
#endif
|
|
void CANtoRS_CheckPacketValid(TCANtoRS *p) {
|
|
Uint8 i;
|
|
Uint16 readCRC, calcCRC; // Ðàñ÷¸òíàÿ è ïðèøåäøàÿ êîíòðîëüíûå ñóììû
|
|
|
|
// Ñíà÷àëà ïðîâåðèì, íå õîòåë ëè ïðåäûäóèùé ïðèíÿòûé ïàêåò çàïóñòèòü êîëáýê
|
|
// Åñëè õîòåë - òî âûïîëíèì, à óæå ïðè ñëåäóþùåì âûçîâå ïðîâåðèì, ïðèøëè ëè äàííûå, ÷òîáû íå ñèëüíî çàãðóæàòü ïðîöåññîð
|
|
if (p->callback_go) {
|
|
p->callback_go = 0;
|
|
p->CounterRes++;
|
|
p->callback(&co1_vars, (TZCanMsg*)&(p->MSG));
|
|
return;
|
|
}
|
|
// Ïîñìîòðèì, ñêîëüêî áàéò íà÷èòàëè â áóôåð. Åñëè ìåíüøå, ÷åì íóæíî (13) - âûõîäèì è æä¸ì ñëåäóþùåãî ðàçà.
|
|
// Åñëè íàñ÷èòàëè - ñáðàñûâàåì ñ÷¸ò÷èê ïðèíÿòûõ áàéò è èä¸ì ïðîâåðÿòü ïîñûëêó
|
|
if (p->ReadPackDataCounter < 13)
|
|
return;
|
|
|
|
p->ReadPackDataCounter = 0;
|
|
|
|
// Ñíà÷àëà ïðîâåðÿåì ñèãíàòóðó, ïåðâûé áàéò ïîñûëêè (äîëæíà áûòü 0x7E)
|
|
// Åñëè ñèãíàòóðà íå ñîøëàñü - ñáðàñûâàåì ñ÷¸ò÷èê íà÷èòàííûõ áàéòîâ, è óâåëè÷èâàåì ÷èñëî ïîòåðÿííûõ ïàêåòîâ
|
|
if (p->tempBuf[0] != 0x7E){
|
|
p->MessDrop3++;
|
|
return;
|
|
}
|
|
|
|
// Åñëè ñèãíàòóðà ñîøëàñü - ñëåäóþùèå 10 áàéò êëàä¸ì â DATA
|
|
for (i = 0; i < CANTORS_READ_DATA_MAX_LEN; i++){
|
|
p->ReadPackData[i] = p->tempBuf[i + 1];
|
|
}
|
|
|
|
// Òåïåðü çàáèðàåì ïîñëåäíèå äâà áàéò ïîñûëêè - CRC. Ñðàíèâàåì ïðèøåäøóþ CRC è ðàñ÷¸òíóþ.
|
|
// Åñëè íå ñîøëîñü - âûõîäèì îòñåäîâà.
|
|
readCRC = ((Uint16)(p->tempBuf[12]) << 8) | ((Uint16)(p->tempBuf[11]));
|
|
calcCRC = CANtoRS_C_CRC(p, (Uint16*)p->ReadPackData, CANTORS_READ_DATA_MAX_LEN);
|
|
if (readCRC != calcCRC) {
|
|
p->CounterWrongCRC++;
|
|
return;
|
|
}
|
|
|
|
// Êîíòðîëüíàÿ ñóììà ñîøëàñü - àíàëèçèðóåì ïàêåò
|
|
CANtoRS_Analysis(p);
|
|
|
|
// Ìîæåò ïîëó÷èòñÿ, ÷òî â ðåçóëüòàòå îáðàáîòêè ïàêåòà ìû óâèäåëè íåîáõîäèìîñòü âûçâàòü êîëëáýê.
|
|
//  òàêîì ñëó÷àå áóäåò âçâåä¸í ôëàã "callback_go". Åñëè ýòî òàê - ìû åãî îáðàáîòàåì ïðè ñëåäóþùåì
|
|
// âûçîâå ôóíêöèè, ÷òîáû íå òðàòèòü ñëèøêîì ìíîãî âðåìåíè. À ïîêà âûõîäèì.
|
|
return;
|
|
|
|
}
|
|
|
|
//! Ôóíêöèÿ äëÿ ïðè¸ìà äàííûõ îò ïåðèôåðèè RS
|
|
//! \memberof TCANtoRS
|
|
#if defined (__GNUC__)
|
|
__attribute__((section(".fastcode")))
|
|
#endif
|
|
void CANtoRS_ReceiveRS(TCANtoRS *p) {
|
|
// ×èòàåì èç ôèôî äàííûå, ïîêà îíè òàì åñòü, ëèáî ïîêà ôèôî íå îïóñòååò
|
|
while ((p->NT_UART->FR_bit.RXFE != 1) && (p->ReadPackDataCounter < 13)) {
|
|
// Åñëè ÷òî-òî ïðèøëî ïî RS, à â ïðîøëûé ðàç ïðèõîäèëî ïî USB - íàäî îáíóëèòü ReadDataCounter
|
|
if (p->lastActiveConnection == CANTOUSB_ACTIVE)
|
|
p->ReadPackDataCounter = 0;
|
|
|
|
p->tempBuf[p->ReadPackDataCounter] = p->NT_UART->DR_bit.DATA;
|
|
p->ReadPackDataCounter++;
|
|
|
|
// Óêàçûâàåì, ÷òî ñåé÷àñ àêòèâåí RS
|
|
p->lastActiveConnection = CANTORS_ACTIVE;
|
|
}
|
|
}
|
|
|
|
//! Ôóíêöèÿ äëÿ ïðè¸ìà äàííûõ îò ïåðèôåðèè USB
|
|
//! \memberof TCANtoRS
|
|
#if defined (__GNUC__)
|
|
__attribute__((section(".fastcode")))
|
|
#endif
|
|
void CANtoRS_ReceiveUSB(TCANtoRS *p) {
|
|
// Uint16 neededBytes;
|
|
// Uint16 tempLen;
|
|
// // Ïðîâåðÿåì, ñêîëüêî åñòü äàííûõ â áóôåðå.
|
|
// // Åñëè áîëüøå, ÷åì íàì íàäî - ÷èòàåì ñêîëüêî íàäî.
|
|
// // Åñëè ìåíüøå, ÷åì íàäî - ÷èòàåì âñ¸.
|
|
// usb_irq_dis();
|
|
// tempLen = usbRxBuf.filledSpace(&usbRxBuf);
|
|
// if (tempLen > 0){
|
|
// // Åñëè ÷òî-òî ïðèøëî ïî USB, à â ïðîøëûé ðàç ïðèõîäèëî ïî RS - íàäî îáíóëèòü ReadDataCounter
|
|
// if (p->lastActiveConnection == CANTORS_ACTIVE)
|
|
// p->ReadPackDataCounter = 0;
|
|
//
|
|
// neededBytes = 13 - p->ReadPackDataCounter;
|
|
//
|
|
// if (tempLen >= neededBytes) {
|
|
// usbRxBuf.get(&usbRxBuf, neededBytes, (Uint8*)(p->tempBuf + p->ReadPackDataCounter));
|
|
// p->ReadPackDataCounter += neededBytes;
|
|
// } else {
|
|
// usbRxBuf.get(&usbRxBuf, tempLen, (Uint8*)(p->tempBuf + p->ReadPackDataCounter));
|
|
// p->ReadPackDataCounter += tempLen;
|
|
// }
|
|
//
|
|
// // Óêàçûâàåì, ÷òî ó íàñ áûë àêòèâåí USB
|
|
// p->lastActiveConnection = CANTOUSB_ACTIVE;
|
|
// }
|
|
// usb_irq_en();
|
|
}
|
|
|
|
//! Ôóíêöèÿ äëÿ ïðè¸ìà è îáðàáîòêè äàííûõ îò ïåðèôåðèè/
|
|
//! Ðàáîòàåò ñðàçó è ñ USB, è ñ RS
|
|
//! \memberof TCANtoRS
|
|
#if defined (__GNUC__)
|
|
__attribute__((section(".fastcode")))
|
|
#endif
|
|
void CANtoRS_Receive(TCANtoRS *p) {
|
|
|
|
#ifdef CANTORS_ENA
|
|
// Åñëè RS-ìîäóëü çàäåéñòâîâàí - îáðàáàòûâàåì UART
|
|
CANtoRS_ReceiveRS(p);
|
|
#endif
|
|
|
|
// Ïðîâåðÿåì ïðèøåäøèå äàííûå
|
|
CANtoRS_CheckPacketValid(p);
|
|
}
|
|
|
|
|
|
/*! Äîëæíà âûçûâàòüñÿ êàæäóþ ñåêóíäó è îòñûëàåò
|
|
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
|
|
#if defined (__GNUC__)
|
|
__attribute__((section(".fastcode")))
|
|
#endif
|
|
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);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*@}*/
|