#include #include #include #include "nex_ui.h" #include //---------------------Nextion-Objekte------------------------ NexEventObj fuellstandInd; NexEventObj pumpeInd; NexEventObj leerInd; NexEventObj feinInd; NexEventObj grobInd; NexEventObj fehlerInd; NexEventObj fuellstandText; //---------------------Alias-Defines------------------------ #define BITBAND_PERI(a,b) ((PERIPH_BB_BASE + (a-PERIPH_BASE)*32 + (b*4))) #define FEHLER *((volatile unsigned long *)(BITBAND_PERI(GPIOC_ODR,1))) // V3 #define LEERBLASEN *((volatile unsigned long *)(BITBAND_PERI(GPIOC_ODR,2))) // V4 #define FEIN *((volatile unsigned long *)(BITBAND_PERI(GPIOC_ODR,13))) // V5 #define GROB *((volatile unsigned long *)(BITBAND_PERI(GPIOB_ODR,7))) // V6 #define PUMPE *((volatile unsigned long *)(BITBAND_PERI(GPIOB_ODR,6))) // V7 #define Switch5 *((volatile unsigned long *)(BITBAND_PERI(GPIOB_IDR,12))) // DIL5 #define Switch4 *((volatile unsigned long *)(BITBAND_PERI(GPIOB_IDR,15))) // DIL4 #define Switch6 *((volatile unsigned long *)(BITBAND_PERI(GPIOB_IDR,14))) // DIL6 #define Switch7 *((volatile unsigned long *)(BITBAND_PERI(GPIOB_IDR,13))) // DIL7 #define Switch1 *((volatile unsigned long *)(BITBAND_PERI(GPIOC_IDR,10))) // DIL1 #define Switch0 *((volatile unsigned long *)(BITBAND_PERI(GPIOC_IDR,6))) // DIL0 #define Switch2 *((volatile unsigned long *)(BITBAND_PERI(GPIOA_IDR,11))) // DIL2 #define Switch3 *((volatile unsigned long *)(BITBAND_PERI(GPIOA_IDR,12))) // DIL3 //---------------------Variablen------------------------ #define NEX_PID_MAIN 0 #define NEX_CID_PROG 1 #define SOLLWERT 0x7F // 127d #define GAP 0x5F // 95d #define NACHLAUF 0x5 volatile unsigned long* Switch[8] ={&Switch0, &Switch1, &Switch2, &Switch3, &Switch4, &Switch5, &Switch6, &Switch7}; int nachlaufOffset = 0; //------------------------------------------------------ void SysTick_Handler() { STD_IncTick(); } void PortConfig(void) { RCC -> APB2ENR |= RCC_APB2ENR_IOPCEN; //Takt für Port C aktivieren RCC -> APB2ENR |= RCC_APB2ENR_IOPBEN; //Takt für Port B aktivieren RCC -> APB2ENR |= RCC_APB2ENR_IOPAEN; //Takt für Port A aktivieren GPIOB -> CRL &= 0x00000000; GPIOB -> CRL = 0x22222222; GPIOB -> CRH &= 0x00000000; GPIOB -> CRH |= 0x88880000; GPIOA -> CRL &= 0x00000000; GPIOA -> CRL = 0x22222222; GPIOA -> CRH &= 0x00000000; GPIOA -> CRH |= 0x00088000; GPIOC -> CRL &= 0x00000000; GPIOC -> CRL |= 0x28222222; GPIOC -> CRH &= 0x00000000; GPIOC -> CRH |= 0x22222822; GPIOA -> ODR &= 0x0000; GPIOB -> ODR &= 0x0000; GPIOC -> ODR &= 0x0000; GPIOA -> ODR |= 0x1800; GPIOB -> ODR |= 0xF000; GPIOC -> ODR |= 0x0440; } void uart2_init(void) { RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN; RCC->APB1ENR |= 0x20000; // UART2 Taktversorgung GPIOA->CRL &= 0xFFFFF0FF; GPIOA->CRL |= 0xB00; GPIOA->CRL &= 0xFFFF0FFF; GPIOA->CRL |= 0x4000; USART2->CR1 &= ~0x1000; // M:--> Start bit, 8 Data bits, n Stop bit USART2->CR1 &= ~0x0400; // PCE: 0: Parity control disabled USART2->CR2 &= ~0x3000; // STOP: 00: 1 Stop bit afungsbil USART2->BRR = 0x1D4C; // set Baudrate to 9600 Baud (SysClk 72Mhz) USART2->CR1 |= 0x0C; // enable Receiver and Transmitter USART2->CR1 |= 0x2000; // Set USART Enable Bit } void uart2_putChar(char zeichen) { while(!((USART2->SR & 0x80) == 0x80)); USART2->DR = zeichen; } void uart2_putString(char* string) { while(*string) { uart2_putChar(*string++); } } char uart2_getChar(void) { while(!(USART2->SR & 0x20)); return ((char) (USART2->DR & 0xFF)); } static void NexEventObj_Init(NexEventObj *obj, uint8_t pid, uint8_t cid, const char *name) { obj->pid = pid; obj->cid = cid; obj->name = name; obj->pophandler = NULL; obj->pushhandler = NULL; } void configNexObjects(void) { NexEventObj_Init(&fuellstandInd, NEX_PID_MAIN, NEX_CID_PROG, "fuellstand"); NexEventObj_Init(&fehlerInd, NEX_PID_MAIN, NEX_CID_PROG, "fehlerInd"); NexEventObj_Init(&leerInd, NEX_PID_MAIN, NEX_CID_PROG, "leerInd"); NexEventObj_Init(&feinInd, NEX_PID_MAIN, NEX_CID_PROG, "feinInd"); NexEventObj_Init(&grobInd, NEX_PID_MAIN, NEX_CID_PROG, "grobInd"); NexEventObj_Init(&pumpeInd, NEX_PID_MAIN, NEX_CID_PROG, "pumpeInd"); NexEventObj_Init(&fuellstandText, NEX_PID_MAIN, NEX_CID_PROG, "fuellstandn"); } void fehler(bool state) { static bool lastStateF = true; static bool firstCallF = true; if (firstCallF) { firstCallF = false; NexProgressBar_setValue(&fehlerInd, 0); return; } else if (state == lastStateF) { return; } lastStateF = state; if(state) { NexProgressBar_setValue(&fehlerInd, 100); FEHLER = 1; uart2_putString("Fehler aufgetreten!\r\n"); } else { NexProgressBar_setValue(&fehlerInd, 0); FEHLER = 0; uart2_putString("Fehler behoben!\r\n"); } return; } void leerBlasen(bool state) { static bool lastStateB; static bool firstCallB = true; if (firstCallB) { firstCallB = false; NexProgressBar_setValue(&leerInd, 0); return; } else if (state == lastStateB) { return; } lastStateB = state; if(state) { NexProgressBar_setValue(&leerInd, 100); LEERBLASEN = 1; uart2_putString("Leerblasventil geoeffnet!\r\n"); } else { NexProgressBar_setValue(&leerInd, 0); LEERBLASEN = 0; uart2_putString("Leerblasventil geschlossen!\r\n"); } return; } void fein(bool state) { static bool lastStateFein; static bool firstCallFein = true; if (firstCallFein) { firstCallFein = false; NexProgressBar_setValue(&feinInd, 0); return; } else if (state == lastStateFein) { return; } lastStateFein = state; if(state) { NexProgressBar_setValue(&feinInd, 100); FEIN = 1; uart2_putString("Feinventil geoeffnet!\r\n"); } else { NexProgressBar_setValue(&feinInd, 0); FEIN = 0; uart2_putString("Feinventil geschlossen!\r\n"); } return; } void grob(bool state) { static bool lastStateGrob; static bool firstCallGrob = true; if (firstCallGrob) { firstCallGrob = false; NexProgressBar_setValue(&grobInd, 0); return; } else if (state == lastStateGrob) { return; } lastStateGrob = state; if(state) { NexProgressBar_setValue(&grobInd, 100); GROB = 1; uart2_putString("Grobventil geoeffnet!\r\n"); } else { NexProgressBar_setValue(&grobInd, 0); GROB = 0; uart2_putString("Grobventil geschlossen!\r\n"); } return; } void pumpe(bool state) { static bool lastState; static bool firstCall = true; if (firstCall) { firstCall = false; NexProgressBar_setValue(&pumpeInd, 0); return; } else if (state == lastState) { return; } lastState = state; if(state) { NexProgressBar_setValue(&pumpeInd, 100); PUMPE = 1; uart2_putString("Pumpe eingeschaltet!\r\n"); } else { NexProgressBar_setValue(&pumpeInd, 0); PUMPE = 0; uart2_putString("Pumpe ausgeschaltet!\r\n"); } return; } void fuellstand(int8_t value) { static bool firstCall = true; static int8_t lastValue = -1; // ungültiger Startwert if(firstCall) { firstCall = false; NexProgressBar_setValue(&fuellstandInd, 0); return; } if (value == lastValue) { return; // nichts geändert ? nichts tun } lastValue = value; if (value >= 0 && value <= 100) { NexProgressBar_setValue(&fuellstandInd, value); uart2_putString("Fuellstand geaendert!\r\n"); } else { NexProgressBar_setValue(&fuellstandInd, 0); uart2_putString("Ungueltiger Fuellstandswert!\r\n"); } } uint8_t toPercent(uint8_t value, uint8_t max) { if (value > max) value = max; return (value * 100 + max / 2) / max; } void setFuellstand(uint8_t value) { char buf[20]; sprintf(buf, "%u l", value); NexText_setText(&fuellstandText, buf); fuellstand(toPercent(value, 255)); } int SwitchesToInt(void) { int result = 0; uint8_t i = 0; for (i = 0; i < 7; i++) { if (!*Switch[i]) { result |= (1 << i); } } return result; } int main(void) { PortConfig(); uart2_init(); NexEventObj *nextlisten_list[] = {NULL}; configNexObjects(); Nex_Init(0); Init_Nex_UI(); fuellstand(0); fehler(false); leerBlasen(false); fein(false); grob(false); pumpe(false); wait_sys_ms(20); bool leerGeblasen = false; bool leitungBenutzt = false; uart2_putString("Dosieranlage V01\r\n"); while(1) { Nex_Event_Loop(nextlisten_list); wait_sys_ms(5); uint8_t istWert = SwitchesToInt(); uint16_t effektiverWert = istWert + nachlaufOffset; if(*Switch[7] == 0) { leerGeblasen = true; leitungBenutzt = false; pumpe(true); if(effektiverWert < SOLLWERT - NACHLAUF) { fein(true); leitungBenutzt = true; } else if(effektiverWert >= SOLLWERT - NACHLAUF) { fein(false); } if(effektiverWert < GAP) { grob(true); leitungBenutzt = true; } else if(effektiverWert < SOLLWERT) { grob(false); } else { grob(false); } setFuellstand(effektiverWert); wait_sys_ms(5); } else { if(leerGeblasen) { pumpe(false); grob(false); fein(false); leerBlasen(true); if(leitungBenutzt) { int time = 3000 / NACHLAUF; uint8_t i = 0; for(i = 0; i < NACHLAUF; i++) { wait_sys_ms(time); nachlaufOffset += 1; setFuellstand(istWert + nachlaufOffset); } } else { wait_sys_ms(3000); } leerBlasen(false); leerGeblasen = false; } } } return 0; }