You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.6 KiB
C
156 lines
5.6 KiB
C
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/wdt.h> // WatchDog
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "avrIOhelper/io-helper.h"
|
|
#include "millis.h"
|
|
#include "uart.h"
|
|
#include "modbus.h"
|
|
|
|
volatile uint32_t inputEdgesBoth;
|
|
volatile uint32_t inputEdgesFalling;
|
|
volatile uint32_t inputEdgesRising;
|
|
|
|
// Timer0
|
|
// 1ms IRQ
|
|
// Used for millis() timing
|
|
void timer0_init()
|
|
{
|
|
TCCR0A = (1<<WGM01); //TIMER0 SET-UP: CTC MODE
|
|
TCCR0B = (1<<CS01)|(1<<CS00); // PS 1:64
|
|
OCR0A = 249; // 1ms reach for clear (16mz:64=>250kHz:250-=>1kHz)
|
|
TIMSK0 |= 1<<OCIE0A; //IRQ on TIMER0 output compareA
|
|
}
|
|
|
|
void timer2_init()
|
|
{
|
|
TCCR2A = (1<<WGM21); //TIMER0 SET-UP: CTC MODE
|
|
TCCR2B|=(1<<CS21); //prescaler 8
|
|
OCR2A = 200;
|
|
TIMSK2|=(1<<OCIE2A);
|
|
}
|
|
|
|
void modbusGet(void) {
|
|
if (modbusGetBusState() & (1<<ReceiveCompleted))
|
|
{
|
|
switch(rxbuffer[1]) {
|
|
case fcPresetSingleRegister:
|
|
case fcPresetMultipleRegisters:
|
|
case fcReadHoldingRegisters:
|
|
modbusExchangeRegisters((void *)outStates,0,1);
|
|
break;
|
|
case fcReadInputRegisters:
|
|
if(modbusRequestedAddress() < 100)
|
|
modbusExchangeRegisters((void *)inStates,0,nrOfInputs/16);
|
|
else if(modbusRequestedAddress() < 200){
|
|
modbusExchangeRegisters((void *)&inputEdgesBoth,100,nrOfInputs/16);
|
|
for(uint16_t i = modbusDataLocation - 100; i < modbusDataLocation-100+(modbusDataAmount*16); i++)
|
|
inputEdgesBoth &= ~(1 << i);
|
|
}
|
|
else if(modbusRequestedAddress() < 300){
|
|
modbusExchangeRegisters((void *)&inputEdgesFalling,200,nrOfInputs/16);
|
|
for(uint16_t i = modbusDataLocation - 200; i < modbusDataLocation-200+(modbusDataAmount*16); i++)
|
|
inputEdgesFalling &= ~(1 << i);
|
|
}
|
|
else if(modbusRequestedAddress() < 400){
|
|
modbusExchangeRegisters((void *)&inputEdgesRising,300,nrOfInputs/16);
|
|
for(uint16_t i = modbusDataLocation - 300; i < modbusDataLocation-300+(modbusDataAmount*16); i++)
|
|
inputEdgesRising &= ~(1 << i);
|
|
}
|
|
break;
|
|
|
|
case fcReadInputStatus:
|
|
if(modbusRequestedAddress() < 100)
|
|
modbusExchangeBits(inStates,0,nrOfInputs);
|
|
else if(modbusRequestedAddress() < 200){
|
|
modbusExchangeBits((void*)&inputEdgesBoth,100,nrOfInputs);
|
|
for(uint16_t i = modbusDataLocation - 100; i < modbusDataLocation+modbusDataAmount-100; i++)
|
|
inputEdgesBoth &= ~(1 << i);
|
|
}
|
|
else if(modbusRequestedAddress() < 300){
|
|
modbusExchangeBits((void*)&inputEdgesFalling,200,nrOfInputs);
|
|
for(uint16_t i = modbusDataLocation - 200; i < modbusDataLocation+modbusDataAmount-200; i++)
|
|
inputEdgesFalling &= ~(1 << i);
|
|
}
|
|
else if(modbusRequestedAddress() < 400){
|
|
modbusExchangeBits((void*)&inputEdgesRising,300,nrOfInputs);
|
|
for(uint16_t i = modbusDataLocation - 300; i < modbusDataLocation+modbusDataAmount-300; i++)
|
|
inputEdgesRising &= ~(1 << i);
|
|
}
|
|
break;
|
|
|
|
case fcForceMultipleCoils:
|
|
case fcForceSingleCoil:
|
|
case fcReadCoilStatus:
|
|
if(modbusRequestedAddress() < 100)
|
|
modbusExchangeBits(outStates,0,nrOfOutputs);
|
|
else if(modbusRequestedAddress() < 200)
|
|
modbusExchangeBits(outStatesBlinking,100,nrOfOutputs);
|
|
else if(modbusRequestedAddress() < 300){
|
|
uint8_t outStatesToggle[sizeof(outStates)];
|
|
memset(outStatesToggle, 0, sizeof(outStatesToggle));
|
|
modbusExchangeBits(outStatesToggle,200,nrOfOutputs);
|
|
for(uint8_t i=0; i<sizeof(outStates); i++){
|
|
outStates[i] ^= outStatesToggle[i];
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
modbusSendException(ecIllegalFunction);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
wdt_enable(WDTO_2S); // set up wdt reset interval 2 second
|
|
|
|
uart_init();
|
|
|
|
ioHelperIoConf();
|
|
timer0_init();// Timer0 millis engine init
|
|
|
|
modbusSetAddress(4);
|
|
modbusInit();
|
|
timer2_init();
|
|
|
|
sei();
|
|
|
|
set_Output(LED_EXTR_FEHLER, BLINK);
|
|
uint32_t timer_blink_outs = millis();
|
|
|
|
printf("moin\n");
|
|
while(1)
|
|
{
|
|
wdt_reset(); // wdt reset ~ every <2000ms
|
|
ioHelperReadPins();
|
|
ioHelperDebounce();
|
|
ioHelperEdgeDetector();
|
|
|
|
inputEdgesBoth |= inStatesBothEdges[0] | ((uint32_t)inStatesBothEdges[1]<<8) | ((uint32_t)inStatesBothEdges[2] << 16) | ((uint32_t)inStatesBothEdges[3]<<24);
|
|
inputEdgesFalling |= inStatesFallingEdge[0] | ((uint32_t)inStatesFallingEdge[1]<<8) | ((uint32_t)inStatesFallingEdge[2] << 16) | ((uint32_t)inStatesFallingEdge[3]<<24);
|
|
inputEdgesRising |= inStatesRisingEdge[0] | ((uint32_t)inStatesRisingEdge[1]<<8) | ((uint32_t)inStatesRisingEdge[2] << 16) | ((uint32_t)inStatesRisingEdge[3]<<24);
|
|
|
|
modbusGet();
|
|
|
|
// Toggle all outs which are set to blinking
|
|
if(millis() - timer_blink_outs > 500){
|
|
ioHelperBlinkOuts();
|
|
timer_blink_outs = millis();
|
|
}
|
|
|
|
ioHelperSetOuts();
|
|
|
|
}
|
|
}
|
|
|
|
ISR(TIMER2_COMPA_vect) { //this ISR is called 9765.625 times per second
|
|
modbusTickTimer();
|
|
}
|
|
|