转载https://www.mikrocontroller.net/topic/106174

//profibus.h

/*!* \file    profibus.h* \brief   Ablaufsteuerung Profibus DP-Slave Kommunikation, h-Datei* \author  © Joerg S.* \date    9.2007 (Erstellung) 7.2008 (Aktueller Stand)* \note    Verwendung nur fuer private Zwecke / Only for non-commercial use*/#ifndef PROFIBUS_H
#define PROFIBUS_H 1///
// Ident Nummer DP Slave
///
#define IDENT_HIGH_BYTE       0x80
#define IDENT_LOW_BYTE        0x70
//////
// Adressen
///
//#define MASTER_ADD            0x02  // SPS Adresse
#define BROADCAST_ADD         0x7F
#define SAP_OFFSET            0x80  // Service Access Point Adress Offset
//////
// Kommandotypen
///
#define SD1                   0x10  // Telegramm ohne Datenfeld
#define SD2                   0x68  // Daten Telegramm variabel
#define SD3                   0xA2  // Daten Telegramm fest
#define SD4                   0xDC  // Token
#define SC                    0xE5  // Kurzquittung
#define ED                    0x16  // Ende
//////
// Function Codes
///
#define REQ_FDL_STATUS        0x49  // SPS: Status Abfrage
#define FDL_STATUS_OK         0x00  // SLA: OK
//#define SEND_DATA
#define SEND_REQ_DATA         0x5D  // SPS: Ausgaenge setzen, Eingaenge lesen
#define SEND_REQ_DATA_T       0x7D  // SPS: Ausgaenge setzen, Eingaenge lesen (Toggle)
#define SEND_REQ_DATA_FIRST   0x6D  // SPS: Erste Anfrage
#define SLAVE_DATA            0x08  // SLA: Daten Eingaenge senden
//////
// Service Access Points (DP Slave) MS0
///
#define SAP_SET_SLAVE_ADR     55  // Master setzt Slave Adresse, Slave Anwortet mit SC
#define SAP_RD_INP            56  // Master fordert Input Daten, Slave sendet Input Daten
#define SAP_RD_OUTP           57  // Master fordert Output Daten, Slave sendet Output Daten
#define SAP_GLOBAL_CONTROL    58  // Master Control, Slave Antwortet nicht
#define SAP_GET_CFG           59  // Master fordert Konfig., Slave sendet Konfiguration
#define SAP_SLAVE_DIAGNOSIS   60  // Master fordert Diagnose, Slave sendet Diagnose Daten
#define SAP_SET_PRM           61  // Master sendet Parameter, Slave sendet SC
#define SAP_CHK_CFG           62  // Master sendet Konfuguration, Slave sendet SC
//////
// SAP: Global Control (Daten Master)
///
#define CLEAR_DATA_           0x02
#define UNFREEZE_             0x04
#define FREEZE_               0x08
#define UNSYNC_               0x10
#define SYNC_                 0x20
//////
// SAP: Diagnose (Antwort Slave)
///
/* Status Byte 1 */
#define STATION_NOT_EXISTENT_ 0x01
#define STATION_NOT_READY_    0x02
#define CFG_FAULT_            0x04
#define EXT_DIAG_             0x08  // Erweiterte Diagnose vorhanden
#define NOT_SUPPORTED_        0x10
#define INV_SLAVE_RESPONSE_   0x20
#define PRM_FAULT_            0x40
#define MASTER_LOCK           0x80/* Status Byte 2 */
#define STATUS_2_DEFAULT      0x04
#define PRM_REQ_              0x01
#define STAT_DIAG_            0x02
#define WD_ON_                0x08
#define FREEZE_MODE_          0x10
#define SYNC_MODE_            0x20
//#define free                  0x40
#define DEACTIVATED_          0x80/* Status Byte 3 */
#define DIAG_SIZE_OK          0x00
#define DIAG_SIZE_ERROR       0x80/* Adresse */
#define MASTER_ADD_DEFAULT    0xFF/* Erweiterte Diagnose (EXT_DIAG_ = 1) */
#define EXT_DIAG_TYPE_        0xC0  // Bit 6-7 ist Diagnose Typ
#define EXT_DIAG_GERAET       0x00  // Wenn Bit 7 und 6 = 00, dann Geraetebezogen
#define EXT_DIAG_KENNUNG      0x40  // Wenn Bit 7 und 6 = 01, dann Kennungsbezogen
#define EXT_DIAG_KANAL        0x80  // Wenn Bit 7 und 6 = 10, dann Kanalbezogen#define EXT_DIAG_BYTE_CNT_    0x3F  // Bit 0-5 sind Anzahl der Diagnose Bytes
//////
// SAP: Set Parameters Request (Daten Master)
///
//#define
//////
// SAP: Check Config Request (Daten Master)
///
#define CFG_DIRECTION_        0x30  // Bit 4-5 ist Richtung. 01 =  Eingang, 10 = Ausgang, 11 = Eingang/Ausgang
#define CFG_INPUT             0x10  // Eingang
#define CFG_OUTPUT            0x20  // Ausgang
#define CFG_INPUT_OUTPUT      0x30  // Eingang/Ausgang
#define CFG_SPECIAL           0x00  // Spezielles Format wenn mehr als 16/32Byte uebertragen werden sollen#define CFG_KONSISTENZ_       0x80  // Bit 7 ist Konsistenz. 0 = Byte oder Wort, 1 = Ueber gesamtes Modul
#define CFG_KONS_BYTE_WORT    0x00  // Byte oder Wort
#define CFG_KONS_MODUL        0x80  // Modul#define CFG_WIDTH_            0x40  // Bit 6 ist IO Breite. 0 = Byte (8bit), 1 = Wort (16bit)
#define CFG_BYTE              0x00  // Byte
#define CFG_WORD              0x40  // Wort/* Kompaktes Format */
#define CFG_BYTE_CNT_         0x0F  // Bit 0-3 sind Anzahl der Bytes oder Worte. 0 = 1 Byte, 1 = 2 Byte usw./* Spezielles Format */
#define CFG_SP_DIRECTION_     0xC0  // Bit 6-7 ist Richtung. 01 =  Eingang, 10 = Ausgang, 11 = Eingang/Ausgang
#define CFG_SP_VOID           0x00  // Leerplatz
#define CFG_SP_INPUT          0x40  // Eingang
#define CFG_SP_OUTPUT         0x80  // Ausgang
#define CFG_SP_INPUT_OPTPUT   0xC0  // Eingang/Ausgang#define CFG_SP_VENDOR_CNT_    0x0F  // Bit 0-3 sind Anzahl der herstellerspezifischen Bytes. 0 = keine/* Spezielles Format / Laengenbyte */
#define CFG_SP_BYTE_CNT_      0x3F  // Bit 0-5 sind Anzahl der Bytes oder Worte. 0 = 1 Byte, 1 = 2 Byte usw.
//////
#define TIMEOUT_MAX_SYN_TIME  33 * DELAY_TBIT // 33 TBit = TSYN
#define TIMEOUT_MAX_RX_TIME   15 * DELAY_TBIT
#define TIMEOUT_MAX_TX_TIME   15 * DELAY_TBIT
#define TIMEOUT_MAX_SDR_TIME  15 * DELAY_TBIT // 15 Tbit = TSDR#define TA_SMCLK_500KHZ_INT   TACTL = MC1 + TASSEL1 + ID_3;
//#define DELAY_TIMER_1_7MS   0x035C  // 33 TB (UART @ 19200)
//#define DELAY_TIMER_782US   0x0187  // 15 TB (UART @ 19200)
//#define DELAY_TBIT          26.04   // UART @ 19200//#define DELAY_TIMER_1_7MS   0x00B1  // 33 TB (UART @ 93750)
//#define DELAY_TIMER_782US   0x0051  // 15 TB (UART @ 93750)
#define DELAY_TBIT            5.33    // UART @ 93750
//////
#define MAX_BUFFER_SIZE       45#define INPUT_DATA_SIZE       35    // Anzahl Bytes die vom Master kommen
#define OUTPUT_DATA_SIZE      35    // Anzahl Bytes die an Master gehen
//////
// Profibus Ablaufsteuerung
///
#define PROFIBUS_WAIT_SYN     1
#define PROFIBUS_WAIT_DATA    2
#define PROFIBUS_GET_DATA     3
#define PROFIBUS_SEND_DATA    4
//////
void          init_Profibus               (void);
void          profibus_RX                 (void);
void          profibus_send_CMD           (unsigned char type,unsigned char function_code,unsigned char sap_offset,char *pdu,unsigned char length_pdu);
void          profibus_TX                 (char *data, unsigned char length);unsigned char checksum                    (char *data, unsigned char length);
///#endif

//profibus.c

/*!* \file    profibus.c* \brief   Ablaufsteuerung Profibus DP-Slave Kommunikation* \author  � Joerg S.* \date    9.2007 (Erstellung) 7.2008 (Aktueller Stand)* \note    Verwendung nur fuer private Zwecke / Only for non-commercial use*/#include "treiber_import.h"char uart_buffer[MAX_BUFFER_SIZE];
unsigned int uart_byte_cnt = 0;
unsigned int uart_transmit_cnt = 0;// Profibus Flags und Variablen
unsigned char profibus_status;
unsigned char slave_addr;
unsigned char master_addr;
unsigned char group;unsigned char data_out_register[OUTPUT_DATA_SIZE];
unsigned char data_in_register [INPUT_DATA_SIZE];
unsigned char Input_Data_size;
unsigned char Output_Data_size;#define TX_IRQ///
/*!* \brief Profibus Timer und Variablen initialisieren*/
void init_Profibus (void)
{unsigned char cnt;// Variablen initialisierenmaster_addr = 0x02;Input_Data_size = 0;Output_Data_size = 0;group = 0;// Slave Adresse aus FLASH holenslave_addr = para_mem_read_byte(EE_BUS_ADDR);// Register loeschenfor (cnt = 0; cnt < OUTPUT_DATA_SIZE; cnt++){data_out_register[cnt] = 0xFF;}for (cnt = 0; cnt < INPUT_DATA_SIZE; cnt++){data_in_register[cnt] = 0x00;}profibus_status = PROFIBUS_WAIT_SYN;// Timer initTAR = 0;TACCR0 = TIMEOUT_MAX_SYN_TIME;TA_SMCLK_500KHZ_INT;TACCTL0 = CCIE;
}
//////
/*!* \brief ISR UART0 Receive*/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR (void)
{// Nur einlesen wenn TSYN abgelaufen ist, oder schon Daten reinkommenif (profibus_status == PROFIBUS_GET_DATA || profibus_status == PROFIBUS_WAIT_DATA){// TSYN abgelaufen, Daten einlesenuart_buffer[uart_byte_cnt++] = UCA0RXBUF;profibus_status = PROFIBUS_GET_DATA;}else{// Daten ignorierenIFG2 &=~UCA0RXIFG;  // IFG zuruecksetzen}// Profibus Timer ruecksetzenTAR = 0;}
//////
/*!* \brief Profibus auswertung*/
void profibus_RX (void)
{unsigned char cnt;unsigned char telegramm_type;unsigned char process_data;// Profibus Datentypenunsigned char destination_add;unsigned char source_add;unsigned char function_code;unsigned char FCS_data;   // Frame Check Sequenceunsigned char PDU_size;   // PDU Groesseunsigned char DSAP_data;  // SAP Destinationunsigned char SSAP_data;  // SAP Sourceprocess_data = FALSE;telegramm_type = uart_buffer[0];switch (telegramm_type){case SD1: // Telegramm ohne Daten, max. 6 Byteif (uart_byte_cnt != 6) break;destination_add = uart_buffer[1];source_add      = uart_buffer[2];function_code   = uart_buffer[3];FCS_data        = uart_buffer[4];if (checksum(&uart_buffer[1], 3) != FCS_data) break;process_data = TRUE;break;case SD2: // Telegramm mit variabler Datenlaengeif (uart_byte_cnt != uart_buffer[1] + 6) break;PDU_size        = uart_buffer[1];destination_add = uart_buffer[4];source_add      = uart_buffer[5];function_code   = uart_buffer[6];FCS_data        = uart_buffer[PDU_size + 4];if (checksum(&uart_buffer[4], PDU_size) != FCS_data) break;process_data = TRUE;break;case SD3: // Telegramm mit 5 Byte Daten, max. 11 Byteif (uart_byte_cnt != 11) break;destination_add = uart_buffer[1];source_add      = uart_buffer[2];function_code   = uart_buffer[3];FCS_data        = uart_buffer[9];if (checksum(&uart_buffer[1], 8) != FCS_data) break;process_data = TRUE;break;case SD4: // Token 3 Byteif (uart_byte_cnt != 3) break;destination_add = uart_buffer[1];source_add      = uart_buffer[2];break;default:break;} // Switch Ende// Nur Daten f黵 eigene Adresse oder Broadcast auswertenif ((destination_add != slave_addr) &&                // Slave(destination_add != slave_addr + SAP_OFFSET) &&   // SAP Slave(destination_add != BROADCAST_ADD) &&             // Broadcast(destination_add != BROADCAST_ADD + SAP_OFFSET))  // SAP Broadcastprocess_data = FALSE;// Nur auswerten wenn Daten OK sindif (process_data == TRUE){master_addr = source_add; // Master Adresse ist Source Adresse// Service Access Point erkannt?if ((destination_add & 0x80) && (source_add & 0x80)){DSAP_data = uart_buffer[7];SSAP_data = uart_buffer[8];// Ablauf Reboot:// 1) SSAP 62 -> DSAP 60 (Get Diagnostics Request)// 2) SSAP 62 -> DSAP 61 (Set Parameters Request)// 3) SSAP 62 -> DSAP 62 (Check Config Request)// 4) SSAP 62 -> DSAP 60 (Get Diagnostics Request)// 5) Data Exchange Request (normaler Zyklus)switch (DSAP_data){case SAP_SET_SLAVE_ADR: // Set Slave Address (SSAP 62 -> DSAP 55)// Adressaenderung siehe Seite 93//new_addr = uart_buffer[9];//IDENT_HIGH_BYTE = uart_buffer[10];//IDENT_LOW_BYTE = uart_buffer[11];//if (uart_buffer[12] & 0x01) adress_aenderung_sperren = TRUE;profibus_send_CMD(SC, 0, SAP_OFFSET, &uart_buffer[0], 0);break;case SAP_GLOBAL_CONTROL: // Global Control Request (SSAP 62 -> DSAP 58)
/*// Wenn "Clear Data" high, dann SPS CPU auf "Stop"if (uart_buffer[9] & CLEAR_DATA_){LED_ERROR_AN;  // Status "SPS nicht bereit"}else{LED_ERROR_AUS; // Status "SPS OK"}// Gruppe berechnenfor (cnt = 0;  uart_buffer[10] != 0; cnt++) uart_buffer[10]>>=1;// Wenn Befehl fuer uns istif (cnt == group){if (uart_buffer[9] & UNFREEZE_){// FREEZE Zustand loeschen}else if (uart_buffer[9] & UNSYNC_){// SYNC Zustand loeschen}else if (uart_buffer[9] & FREEZE_){// Eingaenge nicht mehr neu einlesen}else if (uart_buffer[9] & SYNC_){// Ausgaenge nur bei SYNC Befehl setzen}}
*/break;case SAP_SLAVE_DIAGNOSIS: // Get Diagnostics Request (SSAP 62 -> DSAP 60)// Nach dem Erhalt der Diagnose wechselt der DP-Slave vom Zustand// "Power on Reset" (POR) in den Zustand "Wait Parameter" (WPRM)if (function_code == SEND_REQ_DATA_FIRST){//uart_buffer[4]  = master_addr;                  // Ziel Master (mit SAP Offset)//uart_buffer[5]  = slave_addr + SAP_OFFSET;      // Quelle Slave (mit SAP Offset)//uart_buffer[6]  = SLAVE_DATA;uart_buffer[7]  = SSAP_data;                    // Ziel SAP Masteruart_buffer[8]  = DSAP_data;                    // Quelle SAP Slaveuart_buffer[9]  = STATION_NOT_READY_;           // Status 1uart_buffer[10] = STATUS_2_DEFAULT + PRM_REQ_;  // Status 2uart_buffer[11] = DIAG_SIZE_OK;                 // Status 3uart_buffer[12] = MASTER_ADD_DEFAULT;           // Adresse Masteruart_buffer[13] = IDENT_HIGH_BYTE;              // Ident highuart_buffer[14] = IDENT_LOW_BYTE;               // Ident low//uart_buffer[15] = 0x05;     // Geraetebezogene Diagnose (Anzahl Bytes)//uart_buffer[16] = 0x00;     ////uart_buffer[17] = 0x20;//uart_buffer[18] = 0x20;//uart_buffer[19] = 0x00;profibus_send_CMD(SD2, SLAVE_DATA, SAP_OFFSET, &uart_buffer[7], 8);//13);}else if (function_code == SEND_REQ_DATA || function_code == SEND_REQ_DATA_T){//uart_buffer[4]  = master_addr;                  // Ziel Master (mit SAP Offset)//uart_buffer[5]  = slave_addr + SAP_OFFSET;      // Quelle Slave (mit SAP Offset)//uart_buffer[6]  = SLAVE_DATA;uart_buffer[7]  = SSAP_data;                    // Ziel SAP Masteruart_buffer[8]  = DSAP_data;                    // Quelle SAP Slaveuart_buffer[9]  = 0x00;                         // Status 1uart_buffer[10] = STATUS_2_DEFAULT;             // Status 2uart_buffer[11] = DIAG_SIZE_OK;                 // Status 3uart_buffer[12] = master_addr - SAP_OFFSET;     // Adresse Masteruart_buffer[13] = IDENT_HIGH_BYTE;              // Ident highuart_buffer[14] = IDENT_LOW_BYTE;               // Ident low//uart_buffer[15] = 0x05;     // Geraetebezogene Diagnose (Anzahl Bytes)//uart_buffer[16] = 0x00;     ////uart_buffer[17] = 0x20;//uart_buffer[18] = 0x20;//uart_buffer[19] = 0x00;profibus_send_CMD(SD2, SLAVE_DATA, SAP_OFFSET, &uart_buffer[7], 8);//13);}break;case SAP_SET_PRM: // Set Parameters Request (SSAP 62 -> DSAP 61)// Nach dem Erhalt der Parameter wechselt der DP-Slave vom Zustand// "Wait Parameter" (WPRM) in den Zustand "Wait Configuration" (WCFG)// Master Daten siehe Seite 99// Nur Daten fuer unser Geraet akzeptierenif ((uart_buffer[13] == IDENT_HIGH_BYTE) && (uart_buffer[14] == IDENT_LOW_BYTE)){//uart_buffer[9] = Befehl//uart_buffer[10] = Watchdog 1//uart_buffer[11] = Watchdog 2//uart_buffer[12] = Min TSDR//uart_buffer[13] = Ident H//uart_buffer[14] = Ident L//uart_buffer[15] = Gruppe//uart_buffer[16] = DPV1 Status 1//uart_buffer[17] = DPV1 Status 2//uart_buffer[18] = DPV1 Status 3// Gruppe einlesenfor (group = 0;  uart_buffer[15] != 0; group++) uart_buffer[15]>>=1;profibus_send_CMD(SC, 0, SAP_OFFSET, &uart_buffer[0], 0);}break;case SAP_CHK_CFG: // Check Config Request (SSAP 62 -> DSAP 62)// Nach dem Erhalt der Konfiguration wechselt der DP-Slave vom Zustand// "Wait Configuration" (WCFG) in den Zustand "Data Exchange" (DXCHG)// Master Daten siehe Seite 94// IO Konfiguration:// Kompaktes Format fuer max. 16/32 Byte IO// Spezielles Format fuer max. 64/132 Byte IO// Je nach PDU Datengroesse mehrere Bytes auswerten// LE/LEr - (DA+SA+FC+DSAP+SSAP) = Anzahl Config Bytesfor (cnt = 0; cnt < uart_buffer[1] - 5; cnt++){switch (uart_buffer[9+cnt] & CFG_DIRECTION_){case CFG_INPUT:Input_Data_size = (uart_buffer[9+cnt] & CFG_BYTE_CNT_) + 1;if (uart_buffer[9+cnt] & CFG_WIDTH_ & CFG_WORD)Input_Data_size = Input_Data_size*2;break;case CFG_OUTPUT:Output_Data_size = (uart_buffer[9+cnt] & CFG_BYTE_CNT_) + 1;if (uart_buffer[9+cnt] & CFG_WIDTH_ & CFG_WORD)Output_Data_size = Output_Data_size*2;break;case CFG_INPUT_OUTPUT:Input_Data_size = (uart_buffer[9+cnt] & CFG_BYTE_CNT_) + 1;Output_Data_size = (uart_buffer[9+cnt] & CFG_BYTE_CNT_) + 1;if (uart_buffer[9+cnt] & CFG_WIDTH_ & CFG_WORD){Input_Data_size = Input_Data_size*2;Output_Data_size = Output_Data_size*2;}break;case CFG_SPECIAL:// Spezielles Formatswitch (uart_buffer[9+cnt] & CFG_SP_DIRECTION_){case CFG_SP_VOID:// Leeres Datenfeldbreak;case CFG_SP_INPUT:Input_Data_size = (uart_buffer[10+cnt] & CFG_SP_BYTE_CNT_) + 1;if (uart_buffer[10+cnt] & CFG_WIDTH_ & CFG_WORD)Input_Data_size = Input_Data_size*2;cnt++;  // Dieses Byte haben wir jetzt schonbreak;case CFG_SP_OUTPUT:Output_Data_size = (uart_buffer[10+cnt] & CFG_SP_BYTE_CNT_) + 1;if (uart_buffer[10+cnt] & CFG_WIDTH_ & CFG_WORD)Output_Data_size = Output_Data_size*2;cnt++;  // Dieses Byte haben wir jetzt schonbreak;case CFG_SP_INPUT_OPTPUT:// Erst Ausgang...Output_Data_size = (uart_buffer[10+cnt] & CFG_SP_BYTE_CNT_) + 1;if (uart_buffer[10+cnt] & CFG_WIDTH_ & CFG_WORD)Output_Data_size = Output_Data_size*2;// Dann EingangInput_Data_size = (uart_buffer[11+cnt] & CFG_SP_BYTE_CNT_) + 1;if (uart_buffer[11+cnt] & CFG_WIDTH_ & CFG_WORD)Input_Data_size = Input_Data_size*2;cnt += 2;  // Diese Bytes haben wir jetzt schonbreak;} // Switch Endebreak;default:Input_Data_size = 0;Output_Data_size = 0;break;} // Switch Ende} // For Ende// Kurzquittung wenn alles OK istif (Input_Data_size == INPUT_DATA_SIZE)if (Output_Data_size == OUTPUT_DATA_SIZE)profibus_send_CMD(SC, 0, SAP_OFFSET, &uart_buffer[0], 0);break;default:// Unbekannter SAPbreak;} // Switch DSAP_data Ende}// Ziel: Slave Adresseelse if (destination_add == slave_addr){// Status Abfrageif (function_code == REQ_FDL_STATUS){profibus_send_CMD(SD1, FDL_STATUS_OK, 0, &uart_buffer[0], 0);}// Master sendet Ausgangsdaten und verlangt Eingangsdaten (Send and Request Data)else if (function_code == SEND_REQ_DATA || function_code == SEND_REQ_DATA_T){// Daten von Master einlesenfor (cnt = 0; cnt < INPUT_DATA_SIZE; cnt++){data_in_register[cnt] = uart_buffer[cnt + 7];}// Antwort an Master erstellenuart_buffer[4] = master_addr;uart_buffer[5] = slave_addr;uart_buffer[6] = SLAVE_DATA;// Daten fuer Master in Buffer schreibenfor (cnt = 0; cnt < OUTPUT_DATA_SIZE; cnt++){uart_buffer[cnt + 7] = data_iout_register[cnt];}profibus_send_CMD(SD2, SLAVE_DATA, 0, &uart_buffer[7], OUTPUT_DATA_SIZE);}}} // Daten gueltig Ende}
//////
/*!* \brief Profibus Telegramm zusammenstellen und senden* \param type          Telegrammtyp (SD1, SD2 usw.)* \param function_code Function Code der uebermittelt werden soll* \param sap_offset    Wert des SAP-Offset* \param pdu           Pointer auf Datenfeld (PDU)* \param length_pdu    Laenge der reinen PDU ohne DA, SA oder FC*/
void profibus_send_CMD (unsigned char type,unsigned char function_code,unsigned char sap_offset,char *pdu,unsigned char length_pdu)
{unsigned char length_data;switch(type){case SD1:uart_buffer[0] = SD1;uart_buffer[1] = master_addr;uart_buffer[2] = slave_addr + sap_offset;uart_buffer[3] = function_code;uart_buffer[4] = checksum(&uart_buffer[1], 3);uart_buffer[5] = ED;length_data = 6;break;case SD2:uart_buffer[0] = SD2;uart_buffer[1] = length_pdu + 3;  // Laenge der PDU inkl. DA, SA und FCuart_buffer[2] = length_pdu + 3;uart_buffer[3] = SD2;uart_buffer[4] = master_addr;uart_buffer[5] = slave_addr + sap_offset;uart_buffer[6] = function_code;// Daten werden vor Aufruf der Funktion schon aufgefuelltuart_buffer[7+length_pdu] = checksum(&uart_buffer[4], length_pdu + 3);uart_buffer[8+length_pdu] = ED;length_data = length_pdu + 9;break;case SD3:uart_buffer[0] = SD3;uart_buffer[1] = master_addr;uart_buffer[2] = slave_addr + sap_offset;uart_buffer[3] = function_code;// Daten werden vor Aufruf der Funktion schon aufgefuelltuart_buffer[9] = checksum(&uart_buffer[4], 8);uart_buffer[10] = ED;length_data = 11;break;case SD4:uart_buffer[0] = SD4;uart_buffer[1] = master_addr;uart_buffer[2] = slave_addr + sap_offset;length_data = 3;break;case SC:uart_buffer[0] = SC;length_data = 1;break;default:break;}profibus_TX(&uart_buffer[0], length_data);}
//////
/*!* \brief Telegramm senden* \param data Pointer auf Datenfeld* \param length Laenge der Daten*/
void profibus_TX (char *data, unsigned char length)
{
#ifndef TX_IRQ
// Ohne Interrupt sendenRS485_TX_EN;uart0_send_data(&data[0], length);// Warten bis letztes Byte gesendet worden istwhile (UCA0STAT & UCBUSY);RS485_RX_EN;TACCTL0 = CCIE;  // Interrupt einTAR = 0;TACCR0 = TIMEOUT_MAX_SYN_TIME;profibus_status = PROFIBUS_WAIT_SYN;#endif#ifdef TX_IRQ
// Mit InterruptRS485_TX_EN;TAR = 0;TACCR0 = TIMEOUT_MAX_TX_TIME;   // Timeout setzenprofibus_status = PROFIBUS_SEND_DATA;//DEBUG
TACCTL0 &=~CCIE;  // Interrupt ausuart_byte_cnt = length;         // Anzahl zu sendender Bytesuart_transmit_cnt = 0;          // Zahler fuer gesendete BytesIFG2 |= UCA0TXIFG;              // TX Flag setzenIE2  |= UCA0TXIE;               // Enable USCI_A0 TX interrupt#endif
}
//////
/*!* \brief Checksumme berechnen. Einfaches addieren aller Datenbytes im Telegramm.* \param data Pointer auf Datenfeld* \param length Laenge der Daten* \return Checksumme*/
unsigned char checksum(char *data, unsigned char length)
{unsigned char csum = 0;while(length--){csum += data[length];}return csum;
}
//////
/*!* \brief ISR UART0 Transmit*/
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR (void)
{if (uart_transmit_cnt < uart_byte_cnt) // Alles gesendet?{UCA0TXBUF = uart_buffer[uart_transmit_cnt++];TAR = 0;}else{TAR = 0;// Alles gesendet!while (UCA0STAT & UCBUSY);      // Warten bis letztes Byte gesendet worden istRS485_RX_EN;     // Auf Receive umschaltenTAR = 0;TACCR0 = TIMEOUT_MAX_SYN_TIME;profibus_status = PROFIBUS_WAIT_SYN;IFG2 &= ~UCA0TXIFG;             // TX Flag loeschenIE2  &= ~UCA0TXIE;              // Disable USCI_A0 TX interrupt//DEBUG
TACCTL0 = CCIE;  // Interrupt ein}
}
//////
/*!* \brief ISR TIMER A*/
#pragma vector=TIMERA0_VECTOR
__interrupt void TIMERA0_ISR (void)
{LPM0_EXIT;TAR = 0;switch (profibus_status){case PROFIBUS_WAIT_SYN: // TSYN abgelaufenprofibus_status = PROFIBUS_WAIT_DATA;TACCR0 = TIMEOUT_MAX_SDR_TIME;uart_byte_cnt = 0;break;case PROFIBUS_WAIT_DATA:  // TSDR abgelaufen aber keine Daten dabreak;case PROFIBUS_GET_DATA:   // TSDR abgelaufen und Daten daprofibus_status = PROFIBUS_WAIT_SYN;profibus_RX();break;case PROFIBUS_SEND_DATA:  // Fehler, Timeout abgelaufen, wieder auf empfang gehenprofibus_status = PROFIBUS_WAIT_SYN;TACCR0 = TIMEOUT_MAX_SYN_TIME;RS485_RX_EN;                    // Auf Receive umschaltenbreak;default:break;}
}
///

Profibus DP-Slave in C相关推荐

  1. profibus DP 总线 profibus PA 总线 modbus 总线 有何区别

    profibus DP 总线 profibus PA 总线 modbus 总线 有何区别    PROFBUS是一种国际性的开放式的现场总线标准,它既可以用于高速并且对于时间苛求的数据传输,也可以用于 ...

  2. profibus总线和profibus dp的区别

    profibus总线和profibus dp的区别: PROFBUS是一种国际性的开放式的现场总线标准,它既可以用于高速并且对于时间苛求的数据传输,也可以用于大范围的复杂通讯场合. PROFBUS-D ...

  3. PROFIBUS DP 网络部署的四大要点

    PROFIBUS 线缆 PROFIBUS-DP 物理层支持屏蔽双绞线和光纤两种介质,其中 RS485 传输方式应用最为广泛. PROFIBUS-DP 规定的电缆有 A 型和 B 型两种.技术参数如表中 ...

  4. CANopen / PROFIBUS DP网关

    型号:PCO-150 基本说明:PCO-150在PROFIBUS DP端为从站,CANopen端既可以做主站也可以做从站.即可连接多个CANopen的设备到PROFIBUS DP主站. 1.CANop ...

  5. Profibus DP总线隔离器(协议型)产品性能特点介绍

    Profibus DP协议型现场总线隔离器,符合Profibus DP协议标准,通信速率6Mbps(可选12Mpbs),2路总线电接口数据相互转发,电信号隔离并为电缆系统提供星形链接.接下来就由飞畅科 ...

  6. 简单Profibus/DP实验系统的组建

    简单Profibus/DP实验系统的组建 Writed by 远方 DND-DeviceNet 引言: 为了让更多刚接触到Profibus系统的朋友能对Profibus的网络架构及系统运行机制有一个整 ...

  7. PROFIBUS DP 通讯距离

    PROFIBUS DP的通讯距离与通讯速率有关系,请参考下图: 传输速率(kbits/s) 传输距离(米) 9.6 1200 19.2 1200 45.45 1200 93.75 1200 187.5 ...

  8. Profibus DP/PA/FMS

    PROFIBUS DP(DecentralizedPeriphery 分布式外围设备) 用于现场层的高数数据传输,中央处理器(PLC,PC等)通过高数串行线同分散的现场设备(IO,驱动,阀门等)进行通 ...

  9. HART/PROFIBUS DP网关

    型号:HPM-610 基本说明:实现HART设备与PROFIBUS DP总线系统的互联. 1.支持1个HART通道,HART通道支持连接的HART从站设备多达15个: 2.HART侧可配置为第一主站或 ...

  10. 嵌入式PROFIBUS DP从站接口模块

    型号:PNE-422 基本说明:本产品以OEM的方式,专为自主开发具有PROFIBUS DP 通信功能的产品,提供PROFIBUS-DP从站通信接口,应用简单,可广泛用于各种产品:如变频器.电机启动保 ...

最新文章

  1. 理解Faster R-CNN
  2. qpython3安装lxml_centos python安装lxml报错
  3. 虚拟化十四问:VWmare全面解读虚拟化
  4. 漫画:如何给初学者讲“为什么计算机只认识 0 和 1”?
  5. 02-CSS基础与进阶-day11_2018-09-17-21-35-14
  6. GLib-CRITICAL : g_variant_get_uint32: assertion ‘g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)
  7. Java笔记之入门(一)
  8. 速读原著-TCP/IP(互联网与实现)
  9. 计算机基础考试题及答案多选,2016年计算机一级考试PS及基础多选模拟试题及答案...
  10. 计算机取证之Xplico ——合天网安实验室学习笔记
  11. 好听的摇滚_好听的摇滚歌曲有哪些 十大最好听中国摇滚歌曲
  12. rampUp时间 jmeter
  13. 什么是PaaS平台 ?
  14. 【Pygame实战】俄罗斯方块 | 太好玩了~停不下来,这种版本(Turtle彩版)你肯定没玩过……(经典怀旧:无人不知的俄罗斯方块)
  15. PowerPMAC技术培训------3、PowerPMAC编程工具-IDE
  16. 【12c】12c RMAN新特性之UNTIL AVAILABLE REDO--自动恢复到REDO终点的步骤简化
  17. 算法学习(九)之“宽度优先搜索”
  18. qt 一个应用程序有2个主窗口,任务栏只有一个应用程序图标
  19. 春节灯笼Html代码实现+点击页面出现文字
  20. 金融数学作业——二叉树方法定价(上证50ETF期权)

热门文章

  1. distiller的另一个实例正忙于启动_PYQT5学习(02):利用Qt Designer制作第一个窗口程序
  2. python批量下载网页图片,不用再复制粘贴了(7)
  3. 网页视频播放速度修改器,亲测可用
  4. (附源码)SSM学生寝室管理系统JAVA计算机毕业设计项目
  5. peerDependencies WARNING 警告剖析
  6. encode() decode() 编码解码函数
  7. 又一次移植最新lvgl8到esp32的踩坑记录
  8. 中缀转后缀并分别计算
  9. 图像检索:OPQ索引与HNSW索引
  10. MIT Technology Review 2020年“十大突破性技术”解读 【中国科学基金】2020年第3期发布...