Profibus DP-Slave in C
转载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相关推荐
- profibus DP 总线 profibus PA 总线 modbus 总线 有何区别
profibus DP 总线 profibus PA 总线 modbus 总线 有何区别 PROFBUS是一种国际性的开放式的现场总线标准,它既可以用于高速并且对于时间苛求的数据传输,也可以用于 ...
- profibus总线和profibus dp的区别
profibus总线和profibus dp的区别: PROFBUS是一种国际性的开放式的现场总线标准,它既可以用于高速并且对于时间苛求的数据传输,也可以用于大范围的复杂通讯场合. PROFBUS-D ...
- PROFIBUS DP 网络部署的四大要点
PROFIBUS 线缆 PROFIBUS-DP 物理层支持屏蔽双绞线和光纤两种介质,其中 RS485 传输方式应用最为广泛. PROFIBUS-DP 规定的电缆有 A 型和 B 型两种.技术参数如表中 ...
- CANopen / PROFIBUS DP网关
型号:PCO-150 基本说明:PCO-150在PROFIBUS DP端为从站,CANopen端既可以做主站也可以做从站.即可连接多个CANopen的设备到PROFIBUS DP主站. 1.CANop ...
- Profibus DP总线隔离器(协议型)产品性能特点介绍
Profibus DP协议型现场总线隔离器,符合Profibus DP协议标准,通信速率6Mbps(可选12Mpbs),2路总线电接口数据相互转发,电信号隔离并为电缆系统提供星形链接.接下来就由飞畅科 ...
- 简单Profibus/DP实验系统的组建
简单Profibus/DP实验系统的组建 Writed by 远方 DND-DeviceNet 引言: 为了让更多刚接触到Profibus系统的朋友能对Profibus的网络架构及系统运行机制有一个整 ...
- PROFIBUS DP 通讯距离
PROFIBUS DP的通讯距离与通讯速率有关系,请参考下图: 传输速率(kbits/s) 传输距离(米) 9.6 1200 19.2 1200 45.45 1200 93.75 1200 187.5 ...
- Profibus DP/PA/FMS
PROFIBUS DP(DecentralizedPeriphery 分布式外围设备) 用于现场层的高数数据传输,中央处理器(PLC,PC等)通过高数串行线同分散的现场设备(IO,驱动,阀门等)进行通 ...
- HART/PROFIBUS DP网关
型号:HPM-610 基本说明:实现HART设备与PROFIBUS DP总线系统的互联. 1.支持1个HART通道,HART通道支持连接的HART从站设备多达15个: 2.HART侧可配置为第一主站或 ...
- 嵌入式PROFIBUS DP从站接口模块
型号:PNE-422 基本说明:本产品以OEM的方式,专为自主开发具有PROFIBUS DP 通信功能的产品,提供PROFIBUS-DP从站通信接口,应用简单,可广泛用于各种产品:如变频器.电机启动保 ...
最新文章
- 理解Faster R-CNN
- qpython3安装lxml_centos python安装lxml报错
- 虚拟化十四问:VWmare全面解读虚拟化
- 漫画:如何给初学者讲“为什么计算机只认识 0 和 1”?
- 02-CSS基础与进阶-day11_2018-09-17-21-35-14
- GLib-CRITICAL : g_variant_get_uint32: assertion ‘g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)
- Java笔记之入门(一)
- 速读原著-TCP/IP(互联网与实现)
- 计算机基础考试题及答案多选,2016年计算机一级考试PS及基础多选模拟试题及答案...
- 计算机取证之Xplico ——合天网安实验室学习笔记
- 好听的摇滚_好听的摇滚歌曲有哪些 十大最好听中国摇滚歌曲
- rampUp时间 jmeter
- 什么是PaaS平台 ?
- 【Pygame实战】俄罗斯方块 | 太好玩了~停不下来,这种版本(Turtle彩版)你肯定没玩过……(经典怀旧:无人不知的俄罗斯方块)
- PowerPMAC技术培训------3、PowerPMAC编程工具-IDE
- 【12c】12c RMAN新特性之UNTIL AVAILABLE REDO--自动恢复到REDO终点的步骤简化
- 算法学习(九)之“宽度优先搜索”
- qt 一个应用程序有2个主窗口,任务栏只有一个应用程序图标
- 春节灯笼Html代码实现+点击页面出现文字
- 金融数学作业——二叉树方法定价(上证50ETF期权)
热门文章
- distiller的另一个实例正忙于启动_PYQT5学习(02):利用Qt Designer制作第一个窗口程序
- python批量下载网页图片,不用再复制粘贴了(7)
- 网页视频播放速度修改器,亲测可用
- (附源码)SSM学生寝室管理系统JAVA计算机毕业设计项目
- peerDependencies WARNING 警告剖析
- encode() decode() 编码解码函数
- 又一次移植最新lvgl8到esp32的踩坑记录
- 中缀转后缀并分别计算
- 图像检索:OPQ索引与HNSW索引
- MIT Technology Review 2020年“十大突破性技术”解读 【中国科学基金】2020年第3期发布...