added 3 & 4 digit voltmeter schematics

This commit is contained in:
Eddy
2015-02-17 01:41:28 +03:00
parent 1b567fe1ee
commit b300fb8d06
19 changed files with 1601 additions and 94 deletions

View File

@@ -21,6 +21,7 @@
#include "stm8l.h"
#include "interrupts.h"
#include "soft_i2c.h"
// Top Level Interrupt
INTERRUPT_HANDLER(TLI_IRQHandler, 0){}
@@ -85,26 +86,15 @@ INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14){}
INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13){}
// Timer2 Capture/Compare Interrupt
// store the current counter value and wait for next pulse
// process soft I2C
INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14){
/*
TIM2_CR1 = 0; // stop timer
if(TIM2_SR2){ // overcapture: noice etc.
TIM2_SR2 = 0;
TIM2_SR1 = 0;
ZW_off();
return;
if(TIM2_SR1 & TIM_SR1_UIF){
TIM2_SR1 &= ~TIM_SR1_UIF; // take off flag
tick_counter++;
process_soft_I2C();
}
ZW_catch_bit();
TIM2_SR1 = 0;
TIM2_CNTRH = 0;
TIM2_CNTRL = 0;
*/
}
/*
TIM2_CCMR2 = 1; // IC2 is mapped on TI2FP2
TIM2_CCMR1 = 2; // IC1 is mapped on TI2FP1
*/
#endif // STM8S903
#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \

View File

@@ -22,6 +22,7 @@
#include "main.h"
#include "interrupts.h"
#include "led.h"
#include "soft_i2c.h"
U32 Global_time = 0L; // global time in ms
eeprom_data *saved_data = (eeprom_data*)EEPROM_START_ADDR;
@@ -66,7 +67,8 @@ void eeprom_default_setup(){
int main() {
U32 T_LED = 0L; // time of last digit update
U32 T_time = 0L; // timer
long voltage = 0L;
U8 cntr = 0;
// Configure clocking
CLK_CKDIVR = 0; // F_HSI = 16MHz, f_CPU = 16MHz
// Configure pins
@@ -103,18 +105,46 @@ int main() {
TIM2_IER = TIM_IER_CC2IE;
*/
eeprom_default_setup();
soft_I2C_setup();
soft_I2C_write_config(0xd0, 0x1c); // write configuration
// enable all interrupts
enableInterrupts();
set_display_buf("-----"); // on init show -----
// Loop
do {
if(((unsigned int)(Global_time - T_time) > 1000) || (T_time > Global_time)){ // once per 3 seconds we start measurement
// onse per 300ms refresh displayed value
if(((unsigned int)(Global_time - T_time) > 300) || (T_time > Global_time)){
T_time = Global_time;
display_long(testtimer++,0);
switch (soft_I2C_state){
case SOFT_I2C_NO_DEVICE:
set_display_buf(" EEE "); // error
break;
default: // refresh data
voltage /= cntr;
display_long(voltage, 1);
cntr = 0;
voltage = 0;
}
//display_long(testtimer++,0);
}
if((U8)(Global_time - T_LED) > LED_delay){
if(soft_I2C_state == SOFT_I2C_DATA_READ_OK){
if((readed_data & 1<<7) == 0){ // !RDY == 0
readed_data >>= 8;
// prepare data for rounded output
voltage += (long)(readed_data & 0x3ffff);
cntr++;
}
}
T_LED = Global_time;
show_next_digit();
// refresh data
if(soft_I2C_state == SOFT_I2C_NO_DEVICE){ // try to repeat writing config after an error
soft_I2C_write_config(0xd0, 0x1c);
}else{
soft_I2C_read4bytes(0xd0);
}
}
} while(1);
}

View File

@@ -18,6 +18,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#pragma once
#ifndef __MAIN_H__
#define __MAIN_H__
#include "stm8l.h"
@@ -31,3 +34,7 @@ typedef struct{
U32 max_ADU;
}eeprom_data;
#define CONCAT(a,b) a##_##b
#define PORT(a,b) CONCAT(a,b)
#endif // __MAIN_H__

View File

@@ -0,0 +1,203 @@
/*
* soft_i2c.c - functions emulating I2C
*
* Copyright 2015 Edward V. Emelianoff <eddy@sao.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "soft_i2c.h"
#include "main.h"
// data to transmit: MSB is devaddr, LSB is configuration byte
U16 transmit_cmd;
// == 0 when transmission is in progress
U8 transmission_over = 1;
// tick counter: two ticks for one bit writting and two ticks for empty
U8 tick_counter;
soft_I2C_errors soft_I2C_state = SOFT_I2C_BUSY;
U16 tr_mask = 0; // mask that would be &`ded with transmit_cmd
U32 readed_data; // data readed by I2C
U32 rd_counter = 0; // counter of readed bits == 64 in start of reading; decrements in each readed bit
/*
********************* GPIO (page 111) ********************
* Px_ODR - Output data register bits
* Px_IDR - Pin input values
* Px_DDR - Data direction bits (1 - output)
* Px_CR1 - DDR=0: 0 - floating, 1 - pull-up input; DDR=1: 0 - pseudo-open-drain, 1 - push-pull output [not for "T"]
* Px_CR2 - DDR=0: 0/1 - EXTI disabled/enabled; DDR=1: 0/1 - 2/10MHz
*
*/
/**
* configure pins: SDA - open-drain output
* SCL - push/pull
* configure timer2 as CLK (default speed is 100kHz)
*/
void soft_I2C_setup(){
PORT(I2C_SCL_PORT, DDR) |= I2C_SCL_PIN;
PORT(I2C_SDA_PORT, DDR) |= I2C_SDA_PIN;
PORT(I2C_SDA_PORT, CR1) |= I2C_SDA_PIN;
// Configure timer 2 to generate signals for CLK
TIM2_PSCR = 0; // 16MHz
TIM2_IER = TIM_IER_UIE; // update interrupt enable
TIM2_CR1 |= TIM_CR1_APRE | TIM_CR1_URS; // auto reload + interrupt on overflow
TIM2_ARRH = 0; // set 2.5ms period (100kHz)
TIM2_ARRL = 10;
}
/**
* Set speed of soft I2C
* @param Pulse_len - period (in us) of one pulse
*/
void soft_I2C_set_speed(U16 Pulse_len){
Pulse_len << 2; // multiply on 4 as we have four pulses for each bit, each pulse is 62.5ns
TIM2_ARRH = Pulse_len >> 8; // set speed
TIM2_ARRL = Pulse_len & 0xff;
}
/*
* The data transmission runs only when SCL==1 & SDA have constant level,
* otherwice, if SCL==1 and SDA changes, this is: START(1->0) or STOP(0->1)
*/
void i2c_transmit(){
soft_I2C_state = SOFT_I2C_BUSY;
transmission_over = 0;
tick_counter = 0;
rd_counter = 0;
readed_data = 0;
TIM2_CR1 |= TIM_CR1_CEN; // turn on timer
}
/**
* write a byte to config register of device dev
* @param dev - device address
* @param conf - configuration byte data
*/
U8 soft_I2C_write_config(U8 dev, U8 conf){
if(!transmission_over || (TIM2_CR1&TIM_CR1_CEN)) return SOFT_I2C_BUSY;
dev &= 0xfe; // make sure that r/!w clear
transmit_cmd = dev<<8 || conf;
i2c_transmit();
return SOFT_I2C_OK;
}
/**
* prepare to read 4 bytes of data
* @param dev - device address
*/
U8 soft_I2C_read4bytes(U8 dev){
if(!transmission_over || (TIM2_CR1&TIM_CR1_CEN)) return SOFT_I2C_BUSY;
dev |= 1; // make sure that r/!w is set
transmit_cmd = dev<<8;
i2c_transmit();
return SOFT_I2C_OK;
}
void process_soft_I2C(){
U8 nbit, bitinbyte, tick; // bit number
if(transmission_over){
TIM2_CR1 &= ~TIM_CR1_CEN; // turn off timer
// return line to NOT BUSY state
PORT(I2C_SCL_PORT, ODR) |= I2C_SCL_PIN;
PORT(I2C_SDA_PORT, ODR) |= I2C_SDA_PIN;
return;
}
nbit = tick_counter >> 2; // divide by 4
if(nbit == 0){ // start
switch (tick_counter){
case 1: // 2nd half of start pulse
PORT(I2C_SDA_PORT, ODR) &= ~I2C_SDA_PIN; // clear SDA - Start bit
break;
case 3: // turn to zero both SCL & SDA
PORT(I2C_SCL_PORT, ODR) &= ~I2C_SCL_PIN; // clear SCL, SDA is already cleared
break;
default: // keep current state
;
}
tr_mask = 1<<15; // MSB first
return;
}
bitinbyte = (nbit-1) % 9; // bit counter in each byte
tick = tick_counter % 4; // this is a tick inside bit
// now prepare data
if(bitinbyte == 8){ // ACK
switch (tick){
case 0: // ACK bit
if(nbit == 9) // check line - set ACK to 1
PORT(I2C_SDA_PORT, ODR) |= I2C_SDA_PIN;
else // set ACK to 0 - we are in reading mode
PORT(I2C_SDA_PORT, ODR) &= ~I2C_SDA_PIN;
break;
case 1: // check ACK
if(nbit == 9 && (PORT(I2C_SDA_PORT, ODR) & I2C_SDA_PIN)){ // not zero - very bad
transmission_over = 1;
soft_I2C_state = SOFT_I2C_NO_DEVICE;
return;
}
break;
default: // do nothing
;
}
}else{//data transmision; or STOP
if((tr_mask == 0) && (rd_counter == 0)){ // data sent, now we should send STOP in write mode
// in reading mode - send STOP only when rd_mask == 0
if(tick == 1){ // STOP is 0->1 when CLK is high
PORT(I2C_SDA_PORT, ODR) |= I2C_SDA_PIN;
transmission_over = 1;
if(transmit_cmd & 1<<8) // reading mode
soft_I2C_state = SOFT_I2C_DATA_READ_OK;
else // writting mode
soft_I2C_state = SOFT_I2C_DATA_SEND_OK;
}
}
if(tick == 0){ // start of bit
if(tr_mask){ // transmission
if(transmit_cmd & tr_mask){ // send one
PORT(I2C_SDA_PORT, ODR) |= I2C_SDA_PIN;
} // if we need to send 0, we already have data in zero state
tr_mask >>= 1;
// stop transmission after first byte in read mode
if((tr_mask == 1<<7) && (transmit_cmd & 1<<8)){ // go to reading mode
tr_mask = 0;
rd_counter = 64;
}
}
}else if(tick == 1){ // capture readed data
if((tr_mask == 0) && (transmit_cmd & 1<<8)){ // we are waiting for data
rd_counter--;
readed_data <<= 1;
if(PORT(I2C_SDA_PORT, IDR) & I2C_SDA_PIN) // read 1
readed_data |= 1;
}
}
}
// and at last - set level of SCL
switch (tick){ // set proper value of SCL
case 0: // high pulse
PORT(I2C_SCL_PORT, ODR) |= I2C_SCL_PIN;
break;
case 3: // low pulse & clear SDA
PORT(I2C_SDA_PORT, ODR) &= ~I2C_SDA_PIN;
PORT(I2C_SCL_PORT, ODR) &= ~I2C_SCL_PIN;
break;
default: // do nothing
;
}
}

View File

@@ -0,0 +1,52 @@
/*
* soft_i2c.h
*
* Copyright 2015 Edward V. Emelianoff <eddy@sao.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#pragma once
#ifndef __SOFT_I2C_H__
#define __SOFT_I2C_H__
#include "stm8l.h"
// SDA - PC7, SCL - PD1
#define I2C_SDA_PORT PC
#define I2C_SDA_PIN GPIO_PIN7
#define I2C_SCL_PORT PD
#define I2C_SCL_PIN GPIO_PIN1
typedef enum{
SOFT_I2C_OK // all OK
,SOFT_I2C_BUSY // previous transmission is active
,SOFT_I2C_NO_DEVICE // no device found
,SOFT_I2C_DATA_SEND_OK // data transmitted without errors
,SOFT_I2C_DATA_READ_OK // data readed without errors
} soft_I2C_errors;
extern soft_I2C_errors soft_I2C_state;
extern U32 readed_data;
extern U8 tick_counter;
void soft_I2C_setup();
void soft_I2C_set_speed(U16 Pulse_len);
void process_soft_I2C();
U8 soft_I2C_write_config(U8 dev, U8 conf);
U8 soft_I2C_read4bytes(U8 dev);
#endif // __SOFT_I2C_H__

Binary file not shown.