rewrite with minimal hd444780/modbus example
This commit is contained in:
61
i2c.c
Normal file
61
i2c.c
Normal file
@@ -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
Normal file
26
i2c.h
Normal file
@@ -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
Normal file
187
lcd.c
Normal file
@@ -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
Normal file
46
lcd.h
Normal file
@@ -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
|
||||||
149
main.c
149
main.c
@@ -1,105 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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[4];
|
||||||
|
|
||||||
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
|
|
||||||
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;
|
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;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
modbusSendException(ecIllegalFunction);
|
modbusSendException(ecIllegalFunction);
|
||||||
break;
|
break;
|
||||||
@@ -107,34 +33,25 @@ void modbusGet(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
i2c_init();
|
||||||
|
lcd_init();
|
||||||
|
|
||||||
|
lcd_clear();
|
||||||
|
|
||||||
|
sei();
|
||||||
|
modbusSetAddress(1);
|
||||||
|
modbusInit();
|
||||||
|
|
||||||
|
TCCR0B|=(1<<CS01); //prescaler 8
|
||||||
|
TIMSK0|=(1<<TOIE0);
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
modbusGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ISR(TIMER0_OVF_vect) { //this ISR is called 9765.625 times per second
|
ISR(TIMER0_OVF_vect) { //this ISR is called 9765.625 times per second
|
||||||
modbusTickTimer();
|
modbusTickTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Heater PID control */
|
|
||||||
ISR(TIMER1_OVF_vect) {
|
|
||||||
//output = pid_step(&controller, 1, setpoint_1 - adc_avrg[1]);
|
|
||||||
output = 1;
|
|
||||||
|
|
||||||
//PORTD &= ~(1 << 4);
|
|
||||||
|
|
||||||
if(output > 128)
|
|
||||||
output = 128;
|
|
||||||
|
|
||||||
if(output >= 1){
|
|
||||||
uint32_t tmp = output * 512;
|
|
||||||
if(tmp >= 0x10000)
|
|
||||||
tmp = 0xFFFE;
|
|
||||||
|
|
||||||
OCR1A = tmp;
|
|
||||||
PORTB |= 0x0F;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
OCR1A = 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
ISR(TIMER1_COMPA_vect) {
|
|
||||||
/* turn off outputs */
|
|
||||||
PORTB &= ~(0x0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user