Compare commits

...

10 Commits

@ -0,0 +1,3 @@
-D__AVR_ATxmega32A4__
-I/usr/lib/avr/include
-I./inc

@ -0,0 +1,154 @@
MCU = atxmega32a4
TARGET = main
AVRDUDE_PROGRAMMER = atmelice_pdi
FCPU=2000000UL
BUILDDIR=build
OPT = s
SRC = $(shell find src -name '*.c')
#SRC = main.c
FORMAT = ihex
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS = inc
#### Flags ####
CFLAGS = -mmcu=$(MCU) -I. \
-g -ggdb -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-Wa,-adhlns=$(<:src/%.c=$(BUILDDIR)/%.lst) \
-DF_CPU=$(FCPU)\
$(patsubst %,-I%,$(EXTRAINCDIRS))\
-std=gnu99 \
-fno-builtin
LDFLAGS = -Wl,-Map=$(BUILDDIR)/$(TARGET).map,--cref
# Minimalistic printf version
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires -lm below)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
# -lm = math library
LDFLAGS += -lm
#LDFLAGS += -nostdlib
AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) -U flash:w:$(BUILDDIR)/$(TARGET).hex
#### Define programs and commands. ####
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp
# Define all object files.
OBJ = $(SRC:src/%.c=$(BUILDDIR)/%.o)
# Define all listing files.
LST = $(SRC:src/%.c=$(BUILDDIR)/%.lst)
# Default target: make program!
all: $(TARGET).elf
# $(BUILDDIR)/$(TARGET).lss $(BUILDDIR)/$(TARGET).sym
# $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Program the device.
program: $(BUILDDIR)/$(TARGET).hex $(BUILDDIR)/$(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS)
# Create final output files (.hex, .eep) from ELF output file.
$(BUILDDIR)/%.hex: %.elf
@echo
@echo "creating ihex"
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
$(BUILDDIR)/%.eep: %.elf
@echo
@echo "eeprom"
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
$(BUILDDIR)/%.lss: %.elf
@echo
@echo "listing"
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
$(BUILDDIR)/%.sym: %.elf
@echo
@echo "symbol table"
avr-nm -n $< > $@
# Link: create ELF output file from object files.
#.SECONDARY : $(BUILDDIR)/$(TARGET).elf
#.PRECIOUS : $(OBJ)
$(TARGET).elf: $(OBJ)
@echo
@echo "linking: " $(OBJ)
mkdir -p build
$(CC) $(CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(BUILDDIR)/%.o : src/%.c
@echo
@echo "compiling" $<
mkdir -p build
$(CC) -c $(CFLAGS) $< -o $@
# Target: clean project.
clean:
@echo
@echo "cleaning"
$(REMOVE) $(BUILDDIR)/$(TARGET).hex
$(REMOVE) $(BUILDDIR)/$(TARGET).eep
$(REMOVE) $(BUILDDIR)/$(TARGET).obj
$(REMOVE) $(BUILDDIR)/$(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(BUILDDIR)/$(TARGET).map
$(REMOVE) $(BUILDDIR)/$(TARGET).obj
$(REMOVE) $(BUILDDIR)/$(TARGET).a90
$(REMOVE) $(BUILDDIR)/$(TARGET).sym
$(REMOVE) $(BUILDDIR)/$(TARGET).lnk
$(REMOVE) $(BUILDDIR)/$(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:src/%.c=$(BUILDDIR)/%.s)
$(REMOVE) $(SRC:src/%.c=$(BUILDDIR)/%.d)
$(REMOVE) $(BUILDDIR)/*~
# Automatically generate C source code dependencies.
# (Code originally taken from the GNU make user manual and modified
# (See README.txt Credits).)
#
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
# (see the SHELL variable defined above).
# This may not work with other shells or other seds.
#
$(BUILDDIR)/%.d: %.c
set -e; $(CC) -MM $(CFLAGS) $< \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
[ -s $@ ] || rm -f $@
# Remove the '-' if you want to see the dependency files generated.
-include $(SRC:.c=.d)
# Listing of phony targets.
.PHONY : all clean program

@ -1,7 +1,7 @@
#ifndef _UART_H_
#define _UART_H_
#include <stdio.h>
#include <avr/io.h>
#include "fifo.h"
extern Fifo_t uart0_rx_buffer;
@ -9,7 +9,7 @@ extern Fifo_t uart0_tx_buffer;
void init_uart(void);
void uart_putchar(char c, FILE *stream);
//void putchar(char c);
char get_uart0_char(void);
#endif

@ -0,0 +1,12 @@
#ifndef _UTIL_H_
#define _UTIL_H_
void delay(int ms);
static void printchar(char **str, int c);
static int prints(char **out, const char *string, int width, int pad);
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase);
static int print(char **out, int *varg);
int printf(const char *format, ...);
int sprintf(char *out, const char *format, ...);
#endif

@ -1,4 +1,5 @@
#include "fifo.h"
#include "uart.h"
uint8_t fifo_push(Fifo_t * fifo, uint8_t byte)
{

@ -0,0 +1,102 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <stddef.h>
#include "uart.h"
#include "fifo.h"
#include "util.h"
void init_clk(void)
{
// ========= System Clock configuration =========
// Set to external 16Mhz crystal, using the PLL at *2
// set it to be a 12-16Mhz crystal with a slow start-up time.
OSC.XOSCCTRL = OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc ;
OSC.CTRL |= OSC_XOSCEN_bm ; // enable it
while( (OSC.STATUS & OSC_XOSCRDY_bm) == 0 ){} // wait until it's stable
// The external crystal is now running and stable.
// (Note that it's not yet selected as the clock source)
// Now configure the PLL to be eXternal oscillator * 2
OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2 ;
// now enable the PLL...
OSC.CTRL |= OSC_PLLEN_bm ; // enable the PLL...
while( (OSC.STATUS & OSC_PLLRDY_bm) == 0 ){} // wait until it's stable
// And now, *finally*, we can switch from the internal 2Mhz clock to the PLL
CCP = CCP_IOREG_gc; // protected write follows
CLK.CTRL = CLK_SCLKSEL_PLL_gc; // The System clock is now PLL (16Mhz * 2)
// ==============================================
}
void adc_init(void){
ADCA.CTRLB = 0x00;
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc;
ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc;
uint8_t CalibrationByteL;
uint8_t CalibrationByteH;
NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
CalibrationByteL = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0));
CalibrationByteH = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1));
NVM_CMD = NVM_CMD_NO_OPERATION_gc;
ADCA.CALL = CalibrationByteL;
ADCA.CALH = CalibrationByteH;
ADCA.CTRLA = ADC_ENABLE_bm;
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc;
//
// ADCA.CH1.CTRL = ADC_CH_INPUTMODE1_bm;
// ADCA.CH1.MUXCTRL = ADC_CH_MUXNEG_PIN1_gc;
//
}
uint16_t adc_read(void){
ADCA.CH0.CTRL |= ADC_CH_START_bm;
while(!(ADCA.CH0.INTFLAGS & ADC_CH_CHIF_bm));
ADCA.CH0.INTFLAGS = ADC_CH_CHIF_bm;
return ADCA.CH0.RES;
}
uint16_t adc1_read(void){
ADCA.CH1.CTRL |= ADC_CH_START_bm;
while(!(ADCA.CH1.INTFLAGS & ADC_CH_CHIF_bm));
ADCA.CH1.INTFLAGS = ADC_CH_CHIF_bm;
return ADCA.CH1.RES;
}
int main (void)
{
init_clk();
init_uart();
adc_init();
sei();
PMIC_CTRL = PMIC_LOLVLEN_bm;
PORTA.DIR = 0;
uint32_t val;
//uint32_t val1;
printf("moin!\r\n");
while(1)
{
val = adc_read();
val = val * 1000 / 4096;
printf("val: %03dmV\r\n", val);
//printf("val1: %03d\r\n", val1);
printf("\r\n");
delay(1000);
}
}

@ -0,0 +1,32 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
!_TAG_PROGRAM_VERSION 0.0.0 //
ISR uart.c /^ISR(USARTD0_DRE_vect){$/;" f
ISR uart.c /^ISR(USARTD0_RXC_vect)$/;" f
PAD_RIGHT util.c /^#define PAD_RIGHT /;" d file:
PAD_ZERO util.c /^#define PAD_ZERO /;" d file:
PRINT_BUF_LEN util.c /^#define PRINT_BUF_LEN /;" d file:
bscale uart.c /^const int8_t bscale = 0;$/;" v typeref:typename:const int8_t
bsel uart.c /^const uint16_t bsel = 0;$/;" v typeref:typename:const uint16_t
delay util.c /^void delay(int ms){$/;" f typeref:typename:void
fifo_peek fifo.c /^uint8_t fifo_peek(Fifo_t * fifo){$/;" f typeref:typename:uint8_t
fifo_pop fifo.c /^uint8_t fifo_pop(Fifo_t * fifo, uint8_t *pByte)$/;" f typeref:typename:uint8_t
fifo_push fifo.c /^uint8_t fifo_push(Fifo_t * fifo, uint8_t byte)$/;" f typeref:typename:uint8_t
get_uart0_char uart.c /^char get_uart0_char(void)$/;" f typeref:typename:char
init_clk main.c /^void init_clk(void)$/;" f typeref:typename:void
init_uart uart.c /^void init_uart(void){$/;" f typeref:typename:void
main main.c /^int main (void)$/;" f typeref:typename:int
print util.c /^static int print(char **out, int *varg)$/;" f typeref:typename:int file:
printchar util.c /^static void printchar(char **str, int c)$/;" f typeref:typename:void file:
printf util.c /^int printf(const char *format, ...)$/;" f typeref:typename:int
printi util.c /^static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)$/;" f typeref:typename:int file:
prints util.c /^static int prints(char **out, const char *string, int width, int pad)$/;" f typeref:typename:int file:
putchar uart.c /^void putchar(char c)$/;" f typeref:typename:void
puts uart.c /^void puts(char * s){$/;" f typeref:typename:void
sprintf util.c /^int sprintf(char *out, const char *format, ...)$/;" f typeref:typename:int
uart0_rx_buffer uart.c /^Fifo_t uart0_rx_buffer = {{}, 0, 0};$/;" v typeref:typename:Fifo_t
uart0_tx_buffer uart.c /^Fifo_t uart0_tx_buffer = {{}, 0, 0};$/;" v typeref:typename:Fifo_t

@ -1,15 +1,14 @@
#include <avr/interrupt.h>
#include "uart.h"
#include "util.h"
#include "fifo.h"
Fifo_t uart0_rx_buffer = {{}, 0, 0};
Fifo_t uart0_tx_buffer = {{}, 0, 0};
const uint16_t bsel = 208;
const uint16_t bsel = 13;
const int8_t bscale = 0;
//FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
void init_uart(void){
USARTD0_CTRLC= USART_CHSIZE0_bm | USART_CHSIZE1_bm;
//USARTD0_BAUDCTRLB = 0;
@ -18,27 +17,25 @@ void init_uart(void){
USARTD0.BAUDCTRLB = 0 | (bsel >> 8) | (bscale << USART_BSCALE0_bp);
USARTD0_CTRLB = USART_TXEN_bm | USART_RXEN_bm;
//USARTD0_CTRLA=USART_RXCINTLVL0_bm;
USARTD0_CTRLA=USART_RXCINTLVL0_bm;
PORTD_OUTSET = PIN3_bm;
PORTD_DIRSET = PIN3_bm;
PORTD_OUTCLR = PIN2_bm;
PORTD_DIRCLR = PIN2_bm;
//stdout = &uart_output;
}
void uart_putchar(char c, FILE *stream)
void putchar(char c)
{
fifo_push(&uart0_tx_buffer, c);
USARTD0_CTRLA |= USART_DREINTLVL_LO_gc;
}
//void puts(char * s){
// while (*s) {
// putchar(*s++);
// }
//}
void puts(char * s){
while (*s) {
putchar(*s++);
}
}
char get_uart0_char(void)
{
@ -49,7 +46,7 @@ char get_uart0_char(void)
buffer=USARTD0_DATA;
if ((USARTD0_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0)
return buffer;
}
}
}
ISR(USARTD0_RXC_vect)

@ -0,0 +1,199 @@
void delay(int ms){
for(int i=0;i<ms;i++)
for(long j=0;j<32000/9;j++)
asm("nop");
}
/*
Copyright 2001 Georges Menie
https://www.menie.org/georges/embedded/small_printf_source_code.html
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
putchar is the only external dependency for this file,
if you have a working putchar, just remove the following
define. If the function should be called something else,
replace outbyte(c) by your own function call.
*/
static void printchar(char **str, int c)
{
extern int putchar(int c);
if (str) {
**str = c;
++(*str);
}
else (void)putchar(c);
}
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(char **out, const char *string, int width, int pad)
{
register int pc = 0, padchar = ' ';
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
}
for ( ; *string ; ++string) {
printchar (out, *string);
++pc;
}
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
return pc;
}
/* the following should be enough for 32 bit int */
#define PRINT_BUF_LEN 12
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *s;
register int t, neg = 0, pc = 0;
register unsigned int u = i;
if (i == 0) {
print_buf[0] = '0';
print_buf[1] = '\0';
return prints (out, print_buf, width, pad);
}
if (sg && b == 10 && i < 0) {
neg = 1;
u = -i;
}
s = print_buf + PRINT_BUF_LEN-1;
*s = '\0';
while (u) {
t = u % b;
if( t >= 10 )
t += letbase - '0' - 10;
*--s = t + '0';
u /= b;
}
if (neg) {
if( width && (pad & PAD_ZERO) ) {
printchar (out, '-');
++pc;
--width;
}
else {
*--s = '-';
}
}
return pc + prints (out, s, width, pad);
}
static int print(char **out, int *varg)
{
register int width, pad;
register int pc = 0;
register char *format = (char *)(*varg++);
char scr[2];
for (; *format != 0; ++format) {
if (*format == '%') {
++format;
width = pad = 0;
if (*format == '\0') break;
if (*format == '%') goto out;
if (*format == '-') {
++format;
pad = PAD_RIGHT;
}
while (*format == '0') {
++format;
pad |= PAD_ZERO;
}
for ( ; *format >= '0' && *format <= '9'; ++format) {
width *= 10;
width += *format - '0';
}
if( *format == 's' ) {
register char *s = *((char **)varg++);
pc += prints (out, s?s:"(null)", width, pad);
continue;
}
if( *format == 'd' ) {
pc += printi (out, *varg++, 10, 1, width, pad, 'a');
continue;
}
if( *format == 'x' ) {
pc += printi (out, *varg++, 16, 0, width, pad, 'a');
continue;
}
if( *format == 'X' ) {
pc += printi (out, *varg++, 16, 0, width, pad, 'A');
continue;
}
if( *format == 'u' ) {
pc += printi (out, *varg++, 10, 0, width, pad, 'a');
continue;
}
if( *format == 'c' ) {
/* char are converted to int then pushed on the stack */
scr[0] = *varg++;
scr[1] = '\0';
pc += prints (out, scr, width, pad);
continue;
}
}
else {
out:
printchar (out, *format);
++pc;
}
}
if (out) **out = '\0';
return pc;
}
/* assuming sizeof(void *) == sizeof(int) */
int printf(const char *format, ...)
{
register int *varg = (int *)(&format);
return print(0, varg);
}
int sprintf(char *out, const char *format, ...)
{
register int *varg = (int *)(&format);
return print(&out, varg);
}

@ -1,16 +1,8 @@
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <stddef.h>
#include "yaMBSiavr.h"
#define AVRG 512
volatile uint16_t adc_buffer[AVRG];
volatile float ch_values[9];
#include "pt100.h"
void init_clk(void)
{
@ -42,95 +34,45 @@ void init_timer_100us(){
TCC0.INTCTRLA |= TC_OVFINTLVL_HI_gc;
}
void adc_init(void){
ADCA.CTRLB = ADC_FREERUN_bm;
ADCA.REFCTRL = ADC_REFSEL_VCC_gc;
ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc;
uint8_t CalibrationByteL;
uint8_t CalibrationByteH;
NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
CalibrationByteL = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0));
CalibrationByteH = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1));
NVM_CMD = NVM_CMD_NO_OPERATION_gc;
ADCA.CALL = CalibrationByteL;
ADCA.CALH = CalibrationByteH;
ADCA.CTRLA = ADC_ENABLE_bm;
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
}
uint16_t adc_read(void){
ADCA.CH0.CTRL |= ADC_CH_START_bm;
while(!(ADCA.CH0.INTFLAGS & ADC_CH_CHIF_bm));
ADCA.CH0.INTFLAGS = ADC_CH_CHIF_bm;
return ADCA.CH0.RES;
}
float avrg(uint16_t * values, uint16_t length){
uint64_t res = 0;
//ommit first and last sample
for(uint16_t i=1; i < length-1; i++){
res += values[i];
}
return (float)(res)/(length-2);
}
void dma_init(void){
DMA.CTRL = DMA_ENABLE_bm;
DMA.CH0.CTRLB = DMA_CH_TRNINTLVL_LO_gc;
DMA.CH0.TRFCNT = AVRG * 2;
DMA.CH0.CTRLA = DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_SINGLE_bm;
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;
//repeat endless
DMA.CH0.CTRLA |= DMA_CH_REPEAT_bm;
DMA.CH0.REPCNT = 0;
DMA.CH0.SRCADDR0 = ((uintptr_t)&ADCA.CH0.RES) & 0xFF;
DMA.CH0.SRCADDR1 = (((uintptr_t)&ADCA.CH0.RES) >> 0x08) & 0xFF;
DMA.CH0.SRCADDR2 = (((uintptr_t)&ADCA.CH0.RES) >> 0x0F) & 0xFF;
DMA.CH0.DESTADDR0 = ((uintptr_t)adc_buffer) & 0xFF;
DMA.CH0.DESTADDR1 = ((uintptr_t)adc_buffer >> 0x08) & 0xFF;
DMA.CH0.DESTADDR2 = ((uintptr_t)adc_buffer >> 0x0F) & 0xFF;
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_DESTRELOAD_TRANSACTION_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc;
void io_setup(void){
// LED
PORTD.DIRSET = 1 << 5;
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm;
// pullups for address switch
PORTCFG.MPCMASK = 0xFF;
PORTC.PIN1CTRL = PORT_OPC_PULLUP_gc;
}
void modbusGet(void) {
if (modbusGetBusState() & (1<<ReceiveCompleted))
{
PORTD.OUTSET = 1 << 5;
switch(rxbuffer[1]) {
case fcReadHoldingRegisters: ;
modbusExchangeRegisters(ch_values, 0, 18);
modbusExchangeRegisters((uint16_t*)ch_values, 0, 20);
break;
default:
modbusSendException(ecIllegalFunction);
break;
}
PORTD.OUTCLR = 1 << 5;
}
}
int main(void){
init_clk();
PORTD.DIRSET = 1 << 5;
io_setup();
// blink LED on startup
PORTD.OUTTGL = 1 << 5;
_delay_ms(500);
PORTD.OUTTGL = 1 << 5;
// init pt100 stuff
adc_init();
dma_init();
PORTCFG.MPCMASK = 0xFF;
PORTC.PIN1CTRL = PORT_OPC_PULLUP_gc;
// setup modbus tick timer
init_timer_100us();
PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
@ -147,25 +89,3 @@ int main(void){
ISR(TCC0_OVF_vect){
modbusTickTimer();
}
ISR(DMA_CH0_vect){
static uint8_t pin = 0;
DMA.INTFLAGS |= DMA_CH0TRNIF_bm; // clear flag
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_OFF_gc;
ADCA.CTRLB = 0; // stop ADC
uint8_t old_pin = pin;
pin=(pin+1)%9;
ADCA.CH0.MUXCTRL = pin << ADC_CH_MUXPOS_gp; // give MUX time to switch during averaging
float temp = avrg(adc_buffer, AVRG);
temp = temp - 170;
temp = (temp)/ 3926 * 1.95;
temp = (temp*993.5)/(3.3-temp);
temp = (temp-100)/0.3927;
ch_values[old_pin] = temp;
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;
ADCA.CTRLB = ADC_FREERUN_bm; // start ADC again
}

@ -1,5 +1,5 @@
TARGET = main.elf
FILES = main yaMBSiavr
FILES = main yaMBSiavr pt100
MCU = atxmega32a4
PROGC = x32a4
CC = avr-gcc

@ -0,0 +1,91 @@
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "pt100.h"
uint16_t adc_buffer[AVRG];
volatile float ch_values[10];
void adc_init(void){
ADCA.CTRLB = ADC_FREERUN_bm;
ADCA.REFCTRL = ADC_REFSEL_VCC_gc;
ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc;
uint8_t CalibrationByteL;
uint8_t CalibrationByteH;
NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
CalibrationByteL = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0));
CalibrationByteH = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1));
NVM_CMD = NVM_CMD_NO_OPERATION_gc;
ADCA.CALL = CalibrationByteL;
ADCA.CALH = CalibrationByteH;
ADCA.CTRLA = ADC_ENABLE_bm;
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
}
void dma_init(void){
DMA.CTRL = DMA_ENABLE_bm;
DMA.CH0.CTRLB = DMA_CH_TRNINTLVL_LO_gc;
DMA.CH0.TRFCNT = AVRG * 2;
DMA.CH0.CTRLA = DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_SINGLE_bm;
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;
//repeat endless
DMA.CH0.CTRLA |= DMA_CH_REPEAT_bm;
DMA.CH0.REPCNT = 0;
DMA.CH0.SRCADDR0 = ((uintptr_t)&ADCA.CH0.RES) & 0xFF;
DMA.CH0.SRCADDR1 = (((uintptr_t)&ADCA.CH0.RES) >> 0x08) & 0xFF;
DMA.CH0.SRCADDR2 = (((uintptr_t)&ADCA.CH0.RES) >> 0x0F) & 0xFF;
DMA.CH0.DESTADDR0 = ((uintptr_t)adc_buffer) & 0xFF;
DMA.CH0.DESTADDR1 = ((uintptr_t)adc_buffer >> 0x08) & 0xFF;
DMA.CH0.DESTADDR2 = ((uintptr_t)adc_buffer >> 0x0F) & 0xFF;
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_DESTRELOAD_TRANSACTION_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc;
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm;
}
float avrg(uint16_t * values, uint16_t length){
uint64_t res = 0;
//ommit first and last sample
for(uint16_t i=1; i < length-1; i++){
res += values[i];
}
return (float)(res)/(length-2);
}
ISR(DMA_CH0_vect){
static uint8_t pin = 0;
DMA.INTFLAGS |= DMA_CH0TRNIF_bm; // clear flag
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_OFF_gc;
ADCA.CTRLB = 0; // stop ADC
uint8_t old_pin = pin;
pin=(pin+1)%10;
ADCA.CH0.MUXCTRL = pin << ADC_CH_MUXPOS_gp; // give MUX time to switch during calculation
float temp = avrg(adc_buffer, AVRG);
temp = temp - ADC_0V_COUNT;
temp = (temp)/ (4096-ADC_0V_COUNT) * ADC_MAX_VOLT;
if(old_pin <= 8){ /* pt100 temperature channels */
temp = (temp * REF_OHMS)/(SUPPLY_VOLTS - temp);
temp = (temp-100)/0.3927; //pt100 formula
ch_values[old_pin] = temp;
}
if(old_pin == 9){ /* 24V supply voltage measurement */
// resistor devider 33k and 1k
ch_values[old_pin] = temp * 34;
}
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;
ADCA.CTRLB = ADC_FREERUN_bm; // start ADC again
}

@ -0,0 +1,15 @@
#include <stddef.h>
#define AVRG 512
#define SUPPLY_VOLTS 3.3
#define REF_OHMS 993.5
#define ADC_0V_COUNT 170
#define ADC_MAX_VOLT 1.95
extern volatile float ch_values[10];
void adc_init(void);
void dma_init(void);
float avrg(uint16_t * values, uint16_t length);

@ -74,18 +74,12 @@ void modbusSetAddress(unsigned char newadr)
#if PHYSICAL_TYPE == 485
void transceiver_txen(void)
{
#if BOARD_TYPE == bType5chLedDim
PORTD|=(1<<7);
#endif
TRANSCEIVER_ENABLE_PORT|=(1<<TRANSCEIVER_ENABLE_PIN);
}
void transceiver_rxen(void)
void transceiver_rxen(void)
{
TRANSCEIVER_ENABLE_PORT&=~(1<<TRANSCEIVER_ENABLE_PIN);
#if BOARD_TYPE == bType5chLedDim
PORTD&=~(1<<7);
#endif
}
#endif
@ -209,8 +203,8 @@ ISR(UART_TRANSMIT_INTERRUPT)
#ifndef __AVR_ATxmega32A4__
UART_CONTROL&=~(1<<UART_UDRIE);
#else
USARTD0_CTRLA &= ~(USART_DREINTLVL_gm);
#endif
UART.CTRLA &= ~(USART_DREINTLVL_gm);
#endif//__AVR_ATxmega32A4__
}
}
@ -236,34 +230,32 @@ void modbusInit(void)
UCSRC = (3<<UCSZ0); //Frame Size
#endif
UART_CONTROL = (1<<TXCIE)|(1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // USART receiver and transmitter and receive complete interrupt
#if PHYSICAL_TYPE == 485
TRANSCEIVER_ENABLE_PORT_DDR|=(1<<TRANSCEIVER_ENABLE_PIN);
transceiver_rxen();
#endif
BusState=(1<<TimerActive);
#else
//8bit
USARTD0.CTRLC = USART_CHSIZE0_bm | USART_CHSIZE1_bm;
#else//URSEL
UART.CTRLC = USART_CHSIZE_8BIT_gc;
//38400
USARTD0.BAUDCTRLA = bsel;
USARTD0.BAUDCTRLB = 0 | (bsel >> 8) | (bscale << USART_BSCALE0_bp);
// set baudrate
UART.BAUDCTRLA = UART_BSEL;
UART.BAUDCTRLB = 0 | (UART_BSEL >> 8) | (UART_BSCALE << USART_BSCALE0_bp);
USARTD0.CTRLB = USART_TXEN_bm | USART_RXEN_bm;
UART.CTRLB = USART_TXEN_bm | USART_RXEN_bm;
//Interrupt enable (levels)
USARTD0.CTRLA |= USART_RXCINTLVL_HI_gc;
USARTD0.CTRLA |= USART_TXCINTLVL_HI_gc;
UART.CTRLA |= USART_RXCINTLVL_HI_gc;
UART.CTRLA |= USART_TXCINTLVL_HI_gc;
PORTD_OUTSET = PIN3_bm;
//PORTD_OUTSET = PIN3_bm;
PORTD_DIRSET = PIN3_bm;
PORTD_OUTCLR = PIN2_bm;
PORTD_DIRCLR = PIN2_bm;
//PORTD_OUTCLR = PIN2_bm;
//PORTD_DIRCLR = PIN2_bm;
//TODO Physical type 485
#endif//__AVR_ATxmega32A4__
#if PHYSICAL_TYPE == 485
TRANSCEIVER_ENABLE_PORT_DDR|=(1<<TRANSCEIVER_ENABLE_PIN);
transceiver_rxen();
#endif
BusState=(1<<TimerActive);
#endif
}
/* @brief: Sends a response.
@ -284,8 +276,7 @@ void modbusSendMessage(unsigned char packtop)
#ifndef __AVR_ATxmega32A4__
UART_CONTROL|=(1<<UART_UDRIE);
#else
//TODO use define for usartd
USARTD0_CTRLA |= USART_DREINTLVL_HI_gc;
UART.CTRLA |= USART_DREINTLVL_HI_gc;
#endif
BusState&=~(1<<ReceiveCompleted);

@ -57,15 +57,11 @@ THE POSSIBILITY OF SUCH DAMAGE.
/*
* Definitions for transceiver enable pin.
*/
#if BOARD_TYPE == bType5chLedDim
#define TRANSCEIVER_ENABLE_PORT PORTD
#define TRANSCEIVER_ENABLE_PIN 5
#define TRANSCEIVER_ENABLE_PORT_DDR DDRD
#else
#define TRANSCEIVER_ENABLE_PORT PORTD
#define TRANSCEIVER_ENABLE_PIN 2
#define TRANSCEIVER_ENABLE_PORT_DDR DDRD
#endif
#define TRANSCEIVER_ENABLE_PORT PORTD_OUT
#define TRANSCEIVER_ENABLE_PIN 4
#define TRANSCEIVER_ENABLE_PORT_DDR PORTD_DIR
/**
* @brief
* At the moment the user has to set the value for Baudrate and
@ -188,11 +184,16 @@ THE POSSIBILITY OF SUCH DAMAGE.
#define UART_UDRIE UDRIE
#elif defined(__AVR_ATxmega32A4__)
#define UART USARTD0
#define UART_TRANSMIT_COMPLETE_INTERRUPT USARTD0_TXC_vect
#define UART_RECEIVE_INTERRUPT USARTD0_RXC_vect
#define UART_TRANSMIT_INTERRUPT USARTD0_DRE_vect
#define UART_DATA USARTD0.DATA
//38400 Baud at 32MHz system clock
#define UART_BSEL 51
#define UART_BSCALE 0
#else
#error "no definition available"
@ -219,7 +220,7 @@ THE POSSIBILITY OF SUCH DAMAGE.
* Use 485 or 232, default: 485
* Use 232 for testing purposes or very simple applications that do not require RS485 and bus topology.
*/
#define PHYSICAL_TYPE 232//485 //possible values: 485, 232
#define PHYSICAL_TYPE 485 //possible values: 485, 232
/*
#define modbusBaudrate 38400

@ -0,0 +1,62 @@
import time
from simple_pid import PID
from itertools import count
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import minimalmodbus
tempSens = minimalmodbus.Instrument('/dev/ttyUSB1', 1)
tempSens.serial.baudrate = 38400
OutputDriver = minimalmodbus.Instrument('/dev/ttyUSB1', 1)
OutputDriver.serial.baudrate = 38400
pid = PID(10, 0.01, 0.1, setpoint=100)
plt.style.use('fivethirtyeight')
x_values = []
y_values = []
index = count()
def animate(i):
try:
temp = tempSens.read_float(1, functioncode=4, byteorder=0)
y_values.append(temp)
x_values.append(next(index))
#print(temp)
print(tempSens.read_float(11, functioncode=4, byteorder=0))
# print(temp, end='\t')
# control = pid(temp)
# if(control>100):
# control = 100;
# control = (control/1000.0)
# if(control < 0):
# control = 0
# print(control, end='\t')
# print(0.1-control)
#
# if(control > 0):
# OutputDriver.write_bit(0, 1, functioncode=15)
#
# time.sleep(control)
#
# if(control<0.1):
# OutputDriver.write_bit(0, 0, functioncode=15)
#
# time.sleep(0.1-control)
plt.cla()
plt.scatter(x_values, y_values)
except Exception as e: print(e)
ani = FuncAnimation(plt.gcf(), animate, 2000)
plt.tight_layout()
plt.show()
Loading…
Cancel
Save