motorcontroldemo_028/Vsrc/V_CANtoRS.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);
}
}
}
/*@}*/