rewrite with minimal hd444780/modbus example

rewrite_for_hd774
Eggert Jung 5 years ago
parent fce2b8b26b
commit 76ced85569

61
i2c.c

@ -0,0 +1,61 @@
/*
* i2c.c
*
* Created: 20.01.2018 12:50:54
* Author: Ulrich
*/
#include "i2c.h"
void i2c_init(void){
I2C_PORT |= (1 << SDA_PIN | 1 << SCL_PIN); //Port Pullup
TWCR = 0;
TWSR = 0;
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
_delay_ms(50);
}
//***************************************************************************************
uint8_t i2c_start (uint8_t addr){
uint16_t timeout = 0;
TWCR = (1 << TWINT | 1 << TWSTA | 1 << TWEN);
while(!(TWCR & (1<<TWINT))){
if((timeout++) > 1000) return 1;
}
TWDR = addr;
TWCR = (1 << TWINT | 1 << TWEN);
timeout = 0;
while(!(TWCR & (1<<TWINT))){
if((timeout++) > 1000) return 1;
}
return 0;
}
//***************************************************************************************
uint8_t i2c_byte (uint8_t byte){
uint16_t timeout = 0;
TWDR = byte;
TWCR = (1 << TWINT | 1 << TWEN);
while(!(TWCR & (1<<TWINT))){
if((timeout++) > 1000) return 1;
}
return 0;
}
//***************************************************************************************
uint8_t i2c_readNak(void)
{
uint16_t timeout = 0;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))){
if((timeout++) > 1000) return 0;
}
return TWDR;
}
//***************************************************************************************
void i2c_stop (void){
TWCR = (1 << TWINT | 1 << TWSTO | 1 << TWEN);
TWCR = 0;
}

26
i2c.h

@ -0,0 +1,26 @@
/*
* i2c.h
*
* Created: 20.01.2018 12:51:11
* Author: Ulrich
*/
#ifndef I2C_H_
#define I2C_H_
#include <avr/io.h>
#include <util/delay.h>
//I2C
#define SDA_PIN PC4 //PIN am Atmel
#define SCL_PIN PC5 //PIN am Atmel
#define I2C_PORT PORTC //PORT am Atmel
#define SCL_CLOCK 100000UL
void i2c_init(void);
uint8_t i2c_start (uint8_t);
uint8_t i2c_byte (uint8_t);
uint8_t i2c_readNak(void);
void i2c_stop (void);
#endif /* I2C_H_ */

187
lcd.c

@ -0,0 +1,187 @@
/*
* lcd.c
*
* Created: 20.01.2018 12:51:11
* Author: Ulrich
*/
#include "lcd.h"
volatile unsigned char char_counter = 0;
// output data to lcd
void lcd_out (unsigned char c) {
i2c_start(LCD_I2C_ADDR);
i2c_byte(c | LCD_BACKLIGHT);
i2c_stop();
}
//***************************************************************************************
// CD = Command or Data
void lcd_nibble_out(unsigned char c, unsigned char cd) {
unsigned char out = 0;
unsigned char rs = 0;
if(cd) rs=LCD_RS;
//4 upper bits
if(c & (1<<4)) out |= LCD_D4;
if(c & (1<<5)) out |= LCD_D5;
if(c & (1<<6)) out |= LCD_D6;
if(c & (1<<7)) out |= LCD_D7;
lcd_out(out | rs | LCD_E);
_delay_ms(5);
lcd_out(out | rs);
//4 lower bits
out=0;
if(c & (1<<0)) out |= LCD_D4;
if(c & (1<<1)) out |= LCD_D5;
if(c & (1<<2)) out |= LCD_D6;
if(c & (1<<3)) out |= LCD_D7;
lcd_out(out | rs | LCD_E);
_delay_ms(5);
lcd_out(out | rs );
}
//***************************************************************************************
// clear LCD
void lcd_clear() {
lcd_nibble_out(0x01, 0); // clear display
lcd_nibble_out(0x80, 0);
char_counter = 0;
}
//***************************************************************************************
// LCD home
void lcd_home() {
lcd_nibble_out(0x80, 0);
char_counter = 0;
}
//***************************************************************************************
// Init LCD
void lcd_init() {
unsigned char loop=3;
while(loop--){
lcd_out(LCD_D4 | LCD_D5 | LCD_E);
_delay_ms(10);
lcd_out(LCD_D4 | LCD_D5);
_delay_ms(100);
}
// 4 bit mode
lcd_out(LCD_D5 | LCD_E);
_delay_ms(10);
lcd_out(LCD_D5);
_delay_ms(10);
lcd_nibble_out(0x28, 0);
lcd_nibble_out(0x0C, 0);
lcd_clear();
}
//***************************************************************************************
void lcd_write_char (char c) {
if(char_counter == LCD_WIDTH) lcd_nibble_out(LCD_ADDR_LINE2,0);
if(char_counter == (LCD_WIDTH*2)){
lcd_nibble_out(LCD_ADDR_LINE1,0);
char_counter = 0;
}
char_counter++;
lcd_nibble_out(c, 1);
}
//***************************************************************************************
void lcd_print_str(char *str) {
while (*str != 0){
if(char_counter == LCD_WIDTH) lcd_nibble_out(LCD_ADDR_LINE2,0);
if(char_counter == (LCD_WIDTH*2)){
lcd_nibble_out(LCD_ADDR_LINE1,0);
char_counter = 0;
}
char_counter++;
lcd_nibble_out(*str++, 1);
}
}
//***************************************************************************************
void lcd_write_P (const char *Buffer,...)
{
va_list ap;
va_start (ap, Buffer);
int format_flag;
char str_buffer[10];
char str_null_buffer[10];
char move = 0;
char Base = 0;
int tmp = 0;
char by;
char *ptr;
//Ausgabe der Zeichen
for(;;){
by = pgm_read_byte(Buffer++);
if(by==0) break; // end of format string
if (by == '%'){
by = pgm_read_byte(Buffer++);
if (isdigit(by)>0){
str_null_buffer[0] = by;
str_null_buffer[1] = '\0';
move = atoi(str_null_buffer);
by = pgm_read_byte(Buffer++);
}
switch (by){
case 's':
ptr = va_arg(ap,char *);
while(*ptr) { lcd_write_char(*ptr++); }
break;
case 'b':
Base = 2;
goto ConversionLoop;
case 'c':
//Int to char
format_flag = va_arg(ap,int);
lcd_write_char (format_flag++);
break;
case 'i':
Base = 10;
goto ConversionLoop;
case 'o':
Base = 8;
goto ConversionLoop;
case 'x':
Base = 16;
//****************************
ConversionLoop:
//****************************
itoa(va_arg(ap,int),str_buffer,Base);
int b=0;
while (str_buffer[b++] != 0){};
b--;
if (b<move){
move -=b;
for (tmp = 0;tmp<move;tmp++){
str_null_buffer[tmp] = '0';
}
//tmp ++;
str_null_buffer[tmp] = '\0';
strcat(str_null_buffer,str_buffer);
strcpy(str_buffer,str_null_buffer);
}
lcd_print_str (str_buffer);
move =0;
break;
}
}else{
lcd_write_char (by);
}
}
va_end(ap);
}

46
lcd.h

@ -0,0 +1,46 @@
/*
* lcd.h
*
* Created: 20.01.2018 12:51:11
* Author: Ulrich
*/
#ifndef __LCD_H__
#define __LCD_H__
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <util/delay.h>
#include "i2c.h"
#define LCD_I2C_ADDR 0x4E
//Port Belegung am PCF8574 (1<<PORT)
#define LCD_RS (1<<0)
#define LCD_RW (1<<1)
#define LCD_E (1<<2)
#define LCD_BACKLIGHT (1<<3)
#define LCD_D4 (1<<4)
#define LCD_D5 (1<<5)
#define LCD_D6 (1<<6)
#define LCD_D7 (1<<7)
#define LCD_WIDTH 16
#define LCD_ADDR_LINE1 (0x80)
#define LCD_ADDR_LINE2 (0xC0)
void lcd_init(void);
void lcd_clear(void);
void lcd_home(void);
void lcd_print_str (char *str);
void lcd_write_P (const char *Buffer,...);
#define lcd_write(format, args...) lcd_write_P(PSTR(format) , ## args)
#endif

147
main.c

@ -1,140 +1,57 @@
/*
* LCD_HD44780.c
*
* Created: 20.01.2018 12:51:11
* Author: Ulrich
*/
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <util/delay.h>
#include "lcd.h"
#include "i2c.h"
#include "modbus.h" #include "modbus.h"
#include "pid.h"
#include "adc.h"
#include "i2cmaster.h"
void modbusGet(void);
volatile uint16_t holdingRegisters[40];
volatile float output;
volatile struct pid controller;
volatile float setpoint_1 = 130;
volatile float setpoint_2 = 150;
volatile float setpoint_3 = 150;
int main(){
DDRD |= (1 << 4); // LED
DDRD |= (1 << 3); // FU PWM
DDRD |= (1 << 2); // 485 DE
PORTD |= 1 << 4;
DDRB |= 0x0F; // out channels
PORTD|=(1<<0); // RX
// FU PWM on PD3
TCCR2A |= (1 << COM2B1) | (1 << COM2B0);
TCCR2A |= (1 << WGM21) | (1 << WGM20);
TCCR2B |= (1 << CS21);
modbusSetAddress(1);
modbusInit();
// Modbus Tick Timer
TCCR0B|=(1<<CS01); //prescaler 8
TIMSK0|=(1<<TOIE0);
initADC();
i2c_init();
sei();
_delay_ms(1000);
PORTD &= ~(1 << 4);
init_pid(&controller, 5, 0.2, 0);
// timer for regler volatile uint16_t holdingRegisters[4];
TCCR1B|=(1<<CS12) | (1<<CS10);
TIMSK1|=(1<<TOIE1)|(1<<OCIE1A);
while(1){
modbusGet();
}
}
void modbusGet(void) { void modbusGet(void) {
if (modbusGetBusState() & (1<<ReceiveCompleted)) if (modbusGetBusState() & (1<<ReceiveCompleted))
{ {
switch(rxbuffer[1]) { switch(rxbuffer[1]) {
case fcReadHoldingRegisters: case fcReadHoldingRegisters:
modbusExchangeRegisters(holdingRegisters,0,40);
break;
case fcPresetSingleRegister: case fcPresetSingleRegister:
case fcPresetMultipleRegisters: case fcPresetMultipleRegisters:
if(modbusRequestedAmount()==1) { modbusExchangeRegisters(holdingRegisters,0,4);
modbusExchangeRegisters(holdingRegisters,0,40); lcd_home();
if(modbusIsInRange(0)) lcd_write("test %x", holdingRegisters[0]);
/* analog out for Motor VFD */
OCR2B = holdingRegisters[0] & 0xFF;
if(modbusIsInRange(1)){
/* i2c scanner */
for(int i = 0x0; i < 0xFF; i++){
if(!i2c_start(i)){
holdingRegisters[1] = i;
i2c_stop();
break;
}
i2c_stop();
}
}
} else {
modbusSendException(ecIllegalDataValue);
}
break;
case fcReadCoilStatus:
case fcForceSingleCoil:
case fcForceMultipleCoils:
modbusExchangeBits(&PORTB,0,4);
break;
case fcReadInputRegisters:
if(modbusRequestedAddress()<10)
modbusExchangeRegisters((uint16_t *)&adc_avrg,0,8);
else
modbusExchangeRegisters((uint16_t *)&output,10,4);
break; break;
default: default:
modbusSendException(ecIllegalFunction); modbusSendException(ecIllegalFunction);
break; break;
} }
} }
} }
ISR(TIMER0_OVF_vect) { //this ISR is called 9765.625 times per second int main(void)
modbusTickTimer(); {
} i2c_init();
lcd_init();
/* Heater PID control */ lcd_clear();
ISR(TIMER1_OVF_vect) {
//output = pid_step(&controller, 1, setpoint_1 - adc_avrg[1]);
output = 1;
//PORTD &= ~(1 << 4); sei();
modbusSetAddress(1);
if(output > 128) modbusInit();
output = 128;
if(output >= 1){ TCCR0B|=(1<<CS01); //prescaler 8
uint32_t tmp = output * 512; TIMSK0|=(1<<TOIE0);
if(tmp >= 0x10000)
tmp = 0xFFFE;
OCR1A = tmp; while(1){
PORTB |= 0x0F; modbusGet();
} }
else
OCR1A = 1000;
} }
ISR(TIMER1_COMPA_vect) { ISR(TIMER0_OVF_vect) { //this ISR is called 9765.625 times per second
/* turn off outputs */ modbusTickTimer();
PORTB &= ~(0x0F);
} }

@ -1,5 +1,5 @@
TARGET = main TARGET = main
FILES = main modbus buffer pid twimaster adc FILES = main i2c lcd modbus
MCU = atmega328p MCU = atmega328p
PROGC = m328p PROGC = m328p
CC = avr-gcc CC = avr-gcc

Loading…
Cancel
Save