diff --git a/si7005_softi2c/Makefile b/si7005_softi2c/Makefile new file mode 100644 index 0000000..368a3f8 --- /dev/null +++ b/si7005_softi2c/Makefile @@ -0,0 +1,34 @@ +NAME=si7005 +SDCC=sdcc + +CCFLAGS=-DSTM8S105 -I../ -I/usr/share/sdcc/include -mstm8 --out-fmt-ihx +LDFLAGS= -mstm8 --out-fmt-ihx -lstm8 +FLASHFLAGS=-cstlinkv2 -pstm8s105 + +SRC=$(wildcard *.c) + +OBJ=$(SRC:%.c=%.rel) +TRASH=$(OBJ) $(SRC:%.c=%.rst) $(SRC:%.c=%.asm) $(SRC:%.c=%.lst) +TRASH+=$(SRC:%.c=%.sym) $(NAME).lk $(NAME).map +INDEPENDENT_HEADERS=../stm8l.h ports_definition.h Makefile + +all: $(NAME).ihx + +#$(SRC) : %.c : %.h $(INDEPENDENT_HEADERS) +# @touch $@ +# +#%.h: ; + +clean: + rm -f $(TRASH) + +load: $(NAME).ihx + stm8flash $(FLASHFLAGS) -w $(NAME).ihx + +%.rel: %.c + $(SDCC) $(CCFLAGS) -c $< + +$(NAME).ihx: $(OBJ) + $(SDCC) $(LDFLAGS) $(OBJ) -o $(NAME).ihx + +.PHONY: all diff --git a/si7005_softi2c/client b/si7005_softi2c/client new file mode 100755 index 0000000..72cf0bf Binary files /dev/null and b/si7005_softi2c/client differ diff --git a/si7005_softi2c/interrupts.c b/si7005_softi2c/interrupts.c new file mode 100644 index 0000000..450a9f9 --- /dev/null +++ b/si7005_softi2c/interrupts.c @@ -0,0 +1,194 @@ +/* + * interrupts.c + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 "ports_definition.h" +#include "uart.h" + +// Top Level Interrupt +INTERRUPT_HANDLER(TLI_IRQHandler, 0){} + +// Auto Wake Up Interrupt +INTERRUPT_HANDLER(AWU_IRQHandler, 1){} + +// Clock Controller Interrupt +INTERRUPT_HANDLER(CLK_IRQHandler, 2){} + +// External Interrupt PORTA +INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3){} + +// External Interrupt PORTB +INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4){} + +// External Interrupt PORTC +INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5){ +} + +// External Interrupt PORTD +INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6){ +} + +// External Interrupt PORTE +INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7){} + +#ifdef STM8S903 +// External Interrupt PORTF +INTERRUPT_HANDLER(EXTI_PORTF_IRQHandler, 8){} +#endif // STM8S903 + +#if defined (STM8S208) || defined (STM8AF52Ax) +// CAN RX Interrupt routine. +INTERRUPT_HANDLER(CAN_RX_IRQHandler, 8){} + +// CAN TX Interrupt routine. +INTERRUPT_HANDLER(CAN_TX_IRQHandler, 9){} +#endif // STM8S208 || STM8AF52Ax + +// SPI Interrupt routine. +INTERRUPT_HANDLER(SPI_IRQHandler, 10){} + +// Timer1 Update/Overflow/Trigger/Break Interrupt +INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11){ +} + +// Timer1 Capture/Compare Interrupt routine. +INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12){} + +#ifdef STM8S903 +// Timer5 Update/Overflow/Break/Trigger Interrupt +INTERRUPT_HANDLER(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13){} + +// Timer5 Capture/Compare Interrupt +INTERRUPT_HANDLER(TIM5_CAP_COM_IRQHandler, 14){} + +#else // STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF62Ax or STM8AF52Ax or STM8AF626x + +// Timer2 Update/Overflow/Break Interrupt +INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13){ +} + +// Timer2 Capture/Compare Interrupt +// manage with sending/receiving +INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14){ +/* TIM2_SR1 &= ~TIM_SR1_CC1IF; + onewire_gotlen = TIM2_CCR1H << 8; + onewire_gotlen |= TIM2_CCR1L; + if(onewire_tick_ctr){ // there's some more data to transmit / receive + --onewire_tick_ctr; + if(is_receiver){// receive bits + ow_data >>= 1; + if(onewire_gotlen < ONE_ZERO_BARRIER){ // this is 1 + ow_data |= 0x80; // LSbit first! + } + // in receiver mode we don't need to send byte after ctr is zero! + if(onewire_tick_ctr == 0){ + TIM2_CR1 &= ~TIM_CR1_CEN; + } + }else{// transmit bits + // update CCR2 registers with new values + if(ow_data & 1){ // transmit 1 + TIM2REG(CCR2, BIT_ONE_P); + }else{ // transmit 0 + TIM2REG(CCR2, BIT_ZERO_P); + } + ow_data >>= 1; + } + }else{ // end: turn off timer + TIM2_CR1 &= ~TIM_CR1_CEN; + }*/ +} +#endif // STM8S903 + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF62Ax) || defined (STM8AF52Ax) || defined (STM8AF626x) +// Timer3 Update/Overflow/Break Interrupt +INTERRUPT_HANDLER(TIM3_UPD_OVF_BRK_IRQHandler, 15){} + +// Timer3 Capture/Compare Interrupt +INTERRUPT_HANDLER(TIM3_CAP_COM_IRQHandler, 16){} +#endif // STM8S208, STM8S207 or STM8S105 or STM8AF62Ax or STM8AF52Ax or STM8AF626x + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined (STM8AF62Ax) || defined (STM8AF52Ax) || defined (STM8S903) +// UART1 TX Interrupt +INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17){} + +// UART1 RX Interrupt +INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18){} +#endif // STM8S208 or STM8S207 or STM8S103 or STM8S903 or STM8AF62Ax or STM8AF52Ax + +/* +// I2C Interrupt +INTERRUPT_HANDLER(I2C_IRQHandler, 19){} +*/ + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +// UART2 TX interrupt +INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20){} + +// UART2 RX interrupt +INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21){ + U8 rb; + if(UART2_SR & UART_SR_RXNE){ // data received + rb = UART2_DR; // read received byte & clear RXNE flag + while(!(UART2_SR & UART_SR_TXE)); + UART2_DR = rb; // echo received symbol + UART_rx[UART_rx_cur_i++] = rb; // put received byte into cycled buffer + if(UART_rx_cur_i == UART_rx_start_i){ // Oops: buffer overflow! Just forget old data + UART_rx_start_i++; + check_UART_pointer(UART_rx_start_i); + } + check_UART_pointer(UART_rx_cur_i); + } +} +#endif // STM8S105 or STM8AF626x + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +// UART3 TX interrupt +INTERRUPT_HANDLER(UART3_TX_IRQHandler, 20){} + +// UART3 RX interrupt +INTERRUPT_HANDLER(UART3_RX_IRQHandler, 21){} +#endif // STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +// ADC2 interrupt +INTERRUPT_HANDLER(ADC2_IRQHandler, 22){} +#else +// ADC1 interrupt +INTERRUPT_HANDLER(ADC1_IRQHandler, 22){ +} +#endif // STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax + +#ifdef STM8S903 +// Timer6 Update/Overflow/Trigger Interrupt +INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23){} +#else // STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF52Ax or STM8AF62Ax or STM8AF626x +// Timer4 Update/Overflow Interrupt +INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23){ + if(TIM4_SR & TIM_SR1_UIF){ // update interrupt + Global_time++; // increase timer + } + TIM4_SR = 0; // clear all interrupt flags +} +#endif // STM8S903 + +// Eeprom EEC Interrupt +INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24){} diff --git a/si7005_softi2c/interrupts.h b/si7005_softi2c/interrupts.h new file mode 100644 index 0000000..6edf384 --- /dev/null +++ b/si7005_softi2c/interrupts.h @@ -0,0 +1,144 @@ +/* + * interrupts.h + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 __INTERRUPTS_H__ +#define __INTERRUPTS_H__ + +#include "stm8l.h" + +// Top Level Interrupt +INTERRUPT_DEFINITION(TLI_IRQHandler, 0); + +// Auto Wake Up Interrupt +INTERRUPT_DEFINITION(AWU_IRQHandler, 1); + +// Clock Controller Interrupt +INTERRUPT_DEFINITION(CLK_IRQHandler, 2); + +// External Interrupt PORTA +INTERRUPT_DEFINITION(EXTI_PORTA_IRQHandler, 3); + +// External Interrupt PORTB +INTERRUPT_DEFINITION(EXTI_PORTB_IRQHandler, 4); + +// External Interrupt PORTC +INTERRUPT_DEFINITION(EXTI_PORTC_IRQHandler, 5); + +// External Interrupt PORTD +INTERRUPT_DEFINITION(EXTI_PORTD_IRQHandler, 6); + +// External Interrupt PORTE +INTERRUPT_DEFINITION(EXTI_PORTE_IRQHandler, 7); + +#ifdef STM8S903 +// External Interrupt PORTF +INTERRUPT_DEFINITION(EXTI_PORTF_IRQHandler, 8); +#endif // STM8S903 + +#if defined (STM8S208) || defined (STM8AF52Ax) +// CAN RX Interrupt routine. +INTERRUPT_DEFINITION(CAN_RX_IRQHandler, 8); + +// CAN TX Interrupt routine. +INTERRUPT_DEFINITION(CAN_TX_IRQHandler, 9); +#endif // STM8S208 || STM8AF52Ax + +// SPI Interrupt routine. +INTERRUPT_DEFINITION(SPI_IRQHandler, 10); + +// Timer1 Update/Overflow/Trigger/Break Interrupt +INTERRUPT_DEFINITION(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11); + +// Timer1 Capture/Compare Interrupt routine. +INTERRUPT_DEFINITION(TIM1_CAP_COM_IRQHandler, 12); + +#ifdef STM8S903 +// Timer5 Update/Overflow/Break/Trigger Interrupt +INTERRUPT_DEFINITION(TIM5_UPD_OVF_BRK_TRG_IRQHandler, 13); + +// Timer5 Capture/Compare Interrupt +INTERRUPT_DEFINITION(TIM5_CAP_COM_IRQHandler, 14); + +#else // STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF62Ax or STM8AF52Ax or STM8AF626x +// Timer2 Update/Overflow/Break Interrupt +INTERRUPT_DEFINITION(TIM2_UPD_OVF_BRK_IRQHandler, 13); + +// Timer2 Capture/Compare Interrupt +INTERRUPT_DEFINITION(TIM2_CAP_COM_IRQHandler, 14); +#endif // STM8S903 + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \ + defined(STM8S005) || defined (STM8AF62Ax) || defined (STM8AF52Ax) || defined (STM8AF626x) +// Timer3 Update/Overflow/Break Interrupt +INTERRUPT_DEFINITION(TIM3_UPD_OVF_BRK_IRQHandler, 15); + +// Timer3 Capture/Compare Interrupt +INTERRUPT_DEFINITION(TIM3_CAP_COM_IRQHandler, 16); +#endif // STM8S208, STM8S207 or STM8S105 or STM8AF62Ax or STM8AF52Ax or STM8AF626x + +#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S103) || \ + defined(STM8S003) || defined (STM8AF62Ax) || defined (STM8AF52Ax) || defined (STM8S903) +// UART1 TX Interrupt +INTERRUPT_DEFINITION(UART1_TX_IRQHandler, 17); + +// UART1 RX Interrupt +INTERRUPT_DEFINITION(UART1_RX_IRQHandler, 18); +#endif // STM8S208 or STM8S207 or STM8S103 or STM8S903 or STM8AF62Ax or STM8AF52Ax + +// I2C Interrupt +INTERRUPT_DEFINITION(I2C_IRQHandler, 19); + +#if defined(STM8S105) || defined(STM8S005) || defined (STM8AF626x) +// UART2 TX interrupt +INTERRUPT_DEFINITION(UART2_TX_IRQHandler, 20); + +// UART2 RX interrupt +INTERRUPT_DEFINITION(UART2_RX_IRQHandler, 21); +#endif // STM8S105 or STM8AF626x + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +// UART3 TX interrupt +INTERRUPT_DEFINITION(UART3_TX_IRQHandler, 20); + +// UART3 RX interrupt +INTERRUPT_DEFINITION(UART3_RX_IRQHandler, 21); +#endif // STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax + +#if defined(STM8S207) || defined(STM8S007) || defined(STM8S208) || defined (STM8AF52Ax) || defined (STM8AF62Ax) +// ADC2 interrupt +INTERRUPT_DEFINITION(ADC2_IRQHandler, 22); +#else // STM8S105, STM8S103 or STM8S903 or STM8AF626x +// ADC1 interrupt +INTERRUPT_DEFINITION(ADC1_IRQHandler, 22); +#endif // STM8S208 or STM8S207 or STM8AF52Ax or STM8AF62Ax + +#ifdef STM8S903 +// Timer6 Update/Overflow/Trigger Interrupt +INTERRUPT_DEFINITION(TIM6_UPD_OVF_TRG_IRQHandler, 23); +#else // STM8S208, STM8S207, STM8S105 or STM8S103 or STM8AF52Ax or STM8AF62Ax or STM8AF626x +// Timer4 Update/Overflow Interrupt +INTERRUPT_DEFINITION(TIM4_UPD_OVF_IRQHandler, 23); +#endif // STM8S903 + +// Eeprom EEC Interrupt +INTERRUPT_DEFINITION(EEPROM_EEC_IRQHandler, 24); + +#endif // __INTERRUPTS_H__ diff --git a/si7005_softi2c/main.c b/si7005_softi2c/main.c new file mode 100644 index 0000000..841da71 --- /dev/null +++ b/si7005_softi2c/main.c @@ -0,0 +1,100 @@ +/* + * blinky.c + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 "ports_definition.h" +#include "interrupts.h" +#include "uart.h" +#include "si7005.h" + +volatile unsigned long Global_time = 0L; // global time in ms +U16 paused_val = 500; // interval between LED flashing + +int main() { + unsigned long T = 0L, siT = 0L; + U8 rb; + CFG_GCR |= 1; // disable SWIM + // Configure clocking + CLK_CKDIVR = 0; // F_HSI = 16MHz, f_CPU = 16MHz +// Timer 4 (8 bit) used as system tick timer + // prescaler == 128 (2^7), Tfreq = 125kHz + // period = 1ms, so ARR = 125 + TIM4_PSCR = 7; + TIM4_ARR = 125; + // interrupts: update + TIM4_IER = TIM_IER_UIE; + // auto-reload + interrupt on overflow + enable + TIM4_CR1 = TIM_CR1_APRE | TIM_CR1_URS | TIM_CR1_CEN; + + // PC2 - PP output (on-board LED) + PORT(LED_PORT, DDR) |= LED_PIN; + PORT(LED_PORT, CR1) |= LED_PIN; + + uart_init(); + + si7005_setup(); + + // enable all interrupts + enableInterrupts(); + + // Loop + do{ + if((Global_time - T > paused_val) || (T > Global_time)){ + T = Global_time; + PORT(LED_PORT, ODR) ^= LED_PIN; // blink on-board LED + } + if(UART_read_byte(&rb)){ // buffer isn't empty + switch(rb){ + case 'h': // help + uart_write("\nPROTO:\n+/-\tLED period\n" + "I\tread Si7005 device id\n" + "T\tread themperature\n" + "H\tread humidity\n" + //"O\tread OPT" + ); + break; + case '+': + paused_val += 100; + if(paused_val > 10000) + paused_val = 500; // but not more than 10s + break; + case '-': + paused_val -= 100; + if(paused_val < 500) // but not less than 0.5s + paused_val = 500; + break; + case 'I': + si7005_read_ID(); + break; + case 'T': + si7005_read_T(); + break; + case 'H': + si7005_read_H(); + break; + } + } + if(Global_time != siT){ + siT = Global_time; + si7005_process(); + } + }while(1); +} + + diff --git a/si7005_softi2c/ports_definition.h b/si7005_softi2c/ports_definition.h new file mode 100644 index 0000000..43b16fe --- /dev/null +++ b/si7005_softi2c/ports_definition.h @@ -0,0 +1,46 @@ +/* + * ports_definition.h - definition of ports pins & so on + * + * Copyright 2014 Edward V. Emelianov + * + * 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 __PORTS_DEFINITION_H__ +#define __PORTS_DEFINITION_H__ + +#include "stm8l.h" + +// macro for using in port constructions like PORT(LED_PORT, ODR) = xx +#define CONCAT(a, b) a ## _ ## b +#define PORT(a, b) CONCAT(a , b) + +// on-board LED +#define LED_PORT PC +#define LED_PIN GPIO_PIN2 + +// UART2_TX +#define UART_PORT PD +#define UART_TX_PIN GPIO_PIN5 + +//soft I2C +#define I2C_SDA_PORT PB +#define I2C_SDA_PIN GPIO_PIN4 +#define I2C_SCL_PORT PB +#define I2C_SCL_PIN GPIO_PIN5 + +#endif // __PORTS_DEFINITION_H__ diff --git a/si7005_softi2c/si7005.c b/si7005_softi2c/si7005.c new file mode 100644 index 0000000..38f0d18 --- /dev/null +++ b/si7005_softi2c/si7005.c @@ -0,0 +1,152 @@ +/* + * si7005.c + * + * Copyright 2015 Edward V. Emelianoff + * + * 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 "uart.h" +#include "si7005.h" + +#define DEVID (0x40) + +typedef enum{ + RELAX = 0, + WAITFORT, + WAITFORP +}si7005_state; + +static si7005_state state = RELAX; + +void si7005_setup(){ + i2c_setup(); + i2c_set_addr7(DEVID); +} + +/* + * read device ID + */ +void si7005_read_ID(){ + U8 ID; + i2c_status st = I2C_OK; + if(state != RELAX){ + error_msg("measurements are in process"); + return; + } + if((st = i2c_7bit_send_onebyte(0x11, 0)) == I2C_OK){ + if((st = i2c_7bit_receive_onebyte(&ID,0)) == I2C_OK){ + uart_write("got ID: "); + printUHEX(ID); + UART_send_byte('\n'); + } + } + if(st != I2C_OK){ + uart_write("can't read ID, errcode: "); + printUHEX(st); UART_send_byte('\n'); + } +} + +/* + * start themperature reading + */ +void si7005_read_T(){ + const U8 cmd[2] = {0x03, 0x11}; + i2c_status st = I2C_OK; + if(state != RELAX){ + error_msg("measurements are in process"); + return; + } + st = i2c_7bit_send(cmd, 2, 1); + if(st != I2C_OK){ + error_msg("can't send read sequence, err: "); + printUHEX(st);UART_send_byte('\n'); + return; + } + state = WAITFORT; +} + +/* + * start pressure reading + */ +void si7005_read_P(){ + const U8 cmd[2] = {0x03, 0x01}; + i2c_status st = I2C_OK; + if(state != RELAX){ + error_msg("measurements are in process"); + return; + } + st = i2c_7bit_send(cmd, 2, 1); + if(st != I2C_OK){ + error_msg("can't send read sequence, err: "); + printUHEX(st);UART_send_byte('\n'); + return; + } + state = WAITFORP; +} + +/* + * display readed value in tenths + */ +static void display_data(U8 *d){ + U16 udata = *((int *)d); + long idata = 0L; + switch (state){ + case WAITFORP: // display pressure + udata >>=4; // get 12 bit data + idata = (udata*10L)/16L - 240L; + uart_write("P*10="); + break; + case WAITFORT: // display themperature + udata >>=2; // get 14 bit data + idata = (udata*100L)/32L - 5000L; + uart_write("T*100="); + break; + default: + return; + } + print_long(idata); + UART_send_byte('\n'); +} + +/* + * process state machine + */ +void si7005_process(){ + U8 T[2], b; + i2c_status st; + if(state == RELAX) return; + if(state == WAITFORP || state == WAITFORT){ // poll RDY + if((st = i2c_7bit_send_onebyte(0, 0)) == I2C_OK){ + if(i2c_7bit_receive_onebyte(&b,0) == I2C_OK){ + if(b) return; // !RDY + if((st = i2c_7bit_send_onebyte(1, 0)) == I2C_OK) + if((st = i2c_7bit_receive_twobyte(T,0)) == I2C_OK) + display_data(T); + state = RELAX; + if(st){ + uart_write("can't read value, err: "); + printUHEX(st); UART_send_byte('\n'); + } + } + }else{ + error_msg("can't poll !RDY, err: "); + printUHEX(st); UART_send_byte('\n'); + state = RELAX; + } + } +} diff --git a/si7005_softi2c/si7005.h b/si7005_softi2c/si7005.h new file mode 100644 index 0000000..25d94d9 --- /dev/null +++ b/si7005_softi2c/si7005.h @@ -0,0 +1,32 @@ +/* + * si7005.h + * + * Copyright 2015 Edward V. Emelianoff + * + * 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 __SI7005_H__ +#define __SI7005_H__ + +void si7005_setup(); +void si7005_read_ID(); +void si7005_read_T(); +void si7005_read_P(); +void si7005_process(); + +#endif // __SI7005_H__ diff --git a/si7005_softi2c/si7005.ihx b/si7005_softi2c/si7005.ihx new file mode 100644 index 0000000..b0b8a5b --- /dev/null +++ b/si7005_softi2c/si7005.ihx @@ -0,0 +1,151 @@ +:2080A000808080808080808080808080808080805204AE5240F66B047B04A5202750AE520A +:2080C00041F66B017B04A4804D27FDAE52417B01F7AE00011F02C6000A97C6000A4CC7001B +:2080E0000A4F9572FB027B01F7C60009C1000A2612C600094CC70009C60009A108260472DF +:208100005F0009C6000AA1082604725F000A5B048080AE5342F644241B90CE000E72A900D7 +:1A81200001C6000DA90097C6000CA9009590CF000ECF000CAE53427F808017 +:20813A00AE5240F64824F9AE52417B03F781160390F64D271BAE5240F64824F9AE5245F64F +:20815A00AA08AE5245F790F6905CAE5241F720E0815202C6000AC1000926034F2027160524 +:20817A00AE00011F01C6000997C600094CC700094F9572FB01F690F7C60009A108260472E2 +:20819A005F0009A6015B0281521C5F1F101F0E7B21A1042303CC82787B21A1032603CC82CB +:2081BA00780D212603CC8278965C1F1B4F5F9772FB1B7F4CA10C25F51E1B1C000AA60AF77F +:2081DA007B21A101270E7B21A102271C7B21A104272120301E1FF66B1A5F0F171F0F7B1AB7 +:2081FA006B117B176B0E201C161F90FE5F17101F0E20111E1FE6036B16E602FE6B101F0EC6 +:20821A007B166B11A6096B0D4B0A5F894B001E14891E1489CD8E905B089F887B0E6B138412 +:20823A000A0D5F417B124172FB1BAB30F74B0A5F894B001E14891E1489CD8FC15B081F1098 +:20825A00170E1E1026041E0E27067B0DA1FF2CB87B0D4C5F9772FB1B89CD81485B025B1CDD +:20827A008152110F0E965C1F101E101C000B7F1E16A300007B15A2007B14A2002E14161646 +:20829A0090504F1215974F12149517161F14A6016B0EA60B6B0D4B0A5F894B001E1A891EBD +:2082BA001A89CD8DEB5B089F0A0D5F417B0D4172FB10AB30F74B0A5F894B001E1A891E1A6A +:2082DA0089CD8F0D5B081F1617147B0DA1002C034F2002A6011E1626041E1427034D26B67C +:2082FA00887B0E6B10844D27140D0E27100A0D7B0D6B0F5F7B0F9772FB10A62DF75F7B0FB1 +:20831A009772FB1089CD81485B025B1181521ACE000E1F0DCE000C1F0B5F1F091F070F048E +:20833A000F020F01961C000389CD816B5B024D2603CC83CB7B03A12D260E1E09260A1E0722 +:20835A002606A6016B0420697B03A1302403CC83ED7B03A1392303CC83EDA6016B021E0991 +:20837A00891E09894B0A5F894B00CD90605B081F11170F7B030F195F90977B19909572F95C +:20839A00119F1910979E190F9572A200309FA2006B149EA20017096B077B146B08AE7FFFF4 +:2083BA0013094F12084F120724075F1F091F070F0190CE000E72F20DC6000D120C95C600A5 +:2083DA000C120B9790A327109EA2009FA2002403CC833E0D0126040D0226034F201A7B09A7 +:2083FA00887B0B6B07846B050D0427051E05501F051E1D1605FFA6015B1A81AE849889CD09 +:20841A0081485B021E0389CD81485B024B0ACD813A84817B03A40F6B037B03887B04A10ACE +:20843A00842406AB306B032004AB576B037B0381AE84A189CD81485B027B034EA40F88CD75 +:20845A00842D5B0188CD813A847B0388CD842D5B0188CD813A8481AE5011F6AA20AE50118E +:20847A00F7AE5012F6AA20AE5012F7AE5242A611F7AE5243A606F7AE5245A62CF7810A4560 +:0A849A0052524F523A200030780091 +:0291C5000000A8 +:2084A400CD89224B40CD896984815202725D000B270BAE870089CD84155B02204D4B004B0D +:2084C40011CD8C805B026B024D2625965C4B0089CD8D415B036B024D2616AE871C89CD816F +:2084E400485B027B0188CD844A844B0ACD813A840D022716AE872589CD81485B027B028828 +:20850400CD844A844B0ACD813A845B02815202965CA603F79093905CA61190F7725D000BEC +:20852400270BAE870089CD84155B0220294B014B0289CD8CDB5B044D2718AE873E8889CDA9 +:2085440084155B028488CD844A844B0ACD813A8420043501000B5B02815202965CA603F76C +:208564009093905CA60190F7725D000B270BAE870089CD84155B0220294B014B0289CD8C69 +:20858400DB5B044D2718AE873E8889CD84155B028488CD844A844B0ACD813A8420043502E3 +:2085A400000B5B028152081E0BFEC6000BA101274DC6000BA1022703CC8655A61062905F1A +:2085C4008990894B0A5F894B00CD90605B084B104B004B004B00899089CD8F0D5B085172E0 +:2085E400A200F09FA2006B029EA20017076B057B026B06AE875E89CD81485B022042545462 +:20860400905F8990894B645F894B00CD90605B084B204B004B004B00899089CD8F0D5B0809 +:208624005172A213889FA2006B029EA20017076B057B026B06AE876489CD81485B02200097 +:208644001E07891E0789CD827B5B044B0ACD813A845B08815205725D000B2603CC86FDC6DD +:20866400000BA102270AC6000BA1012703CC86FD4B004B00CD8C805B026B054D2661961C69 +:2086840000044B0089CD8D415B034D2703CC86FD0D042703CC86FD4B004B01CD8C805B02E8 +:2086A4006B034D261A965C9093894B009089CD8D905B03856B034D260689CD85A95B0272B2 +:2086C4005F000B0D032732AE876B89CD81485B027B0388CD844A844B0ACD813A84201AAE39 +:2086E400878389CD84155B027B0588CD844A844B0ACD813A84725F000B5B05816D65617335 +:208704007572656D656E74732061726520696E2070726F6365737300676F742049443A2023 +:208724000063616E277420726561642049442C20657272636F64653A200063616E27742088 +:2087440073656E6420726561642073657175656E63652C206572723A2000482A31303D0037 +:20876400542A3130303D0063616E277420726561642076616C75652C206572723A20006391 +:16878400616E277420706F6C6C20215244592C206572723A20007F +:0191C70000A7 +:208000008200808382000000820080A0820080A1820080A2820080A3820080A4820080A57E +:20802000820080A6820080A78200000082000000820080A8820080A9820080AA820080AB3D +:20804000820080AC820080AD820080AE820000008200000082008DEA820080AF820080B0B3 +:20806000820081118200811282008139820000008200000082000000820000008200000011 +:1D808300AE00082707724F00005A26F9AE000B2709D691C4D700085A26F7CC80808C +:03808000CC879A10 +:20879A00520D5F1F081F065F1F041F02AE7F60F6AA01AE7F60F7AE50C67FAE5345A607F733 +:2087BA00AE5346A67DF7AE5341A601F7AE5340A685F7AE500CF6AA04AE500CF7AE500DF64B +:2087DA00AA04AE500DF7CD8471CD84A49ACE000E72F0081F0CC6000D12076B0BC6000C12C7 +:2087FA0006CE0010905F88130D909F120C909E12015B012511CE000E1308C6000D1207C61B +:20881A00000C12062414CE000E1F08CE000C1F06AE500AF6A804AE500AF7965C89CD816B03 +:20883A005B024D2603CC88AA7B01A12B271FA12D2736A1482757A1492749A154274AA16864 +:20885A00264EAE88CE89CD81485B022043CE00101C0064CF0010CE0010A32710233235F434 +:20887A000011350100102028CE00101D0064CF0010CE0010A301F4241735F40011350100E0 +:20889A0010200DCD84AE2008CD85112003CD855D1E04C3000E260A1E02C3000C2603CC8797 +:2088BA00E7CE000E1F04CE000C1F02CD8658CC87E75B0D810A50524F544F3A0A2B2F2D097D +:2088DA004C454420706572696F640A490972656164205369373030352064657669636520B6 +:2088FA0069640A540972656164207468656D70657261747572650A48097265616420687564 +:08891A006D69646974790A00BB +:0691C8000000000001F4AC +:20892200AE5005F6AA20AE5005F7AE5005F6AA10AE5005F7AE5007F6AA20AE5007F7AE500C +:2089420007F6AA10AE5007F7AE5009F6AA20AE5009F7AE5009F6AA10AE5009F7AE530C7F5C +:20896200AE5300A608F7817B0348C70013C60013AA01C7001281AE5005F6AA10AE5005F7A3 +:20898200AE530D7FAE530EA61EF7AE5300F6AA01AE5300F7AE5302F6A0014F494425F5AEA6 +:2089A20053027FAE5005F6A4DFAE5005F7AE530D7FAE530EA61EF7AE5300F6AA01AE530071 +:2089C200F7AE5302F6A0014F494425F5AE53027FAE5005F6A4EFAE5005F7AE530D7FAE5378 +:2089E2000EA61EF7AE5300F6AA01AE5300F7AE5302F6A0014F494425F5AE53027F81AE5081 +:208A020005F6A4DFAE5005F7AE5005F6A4EFAE5005F7AE530D7FAE530EA61EF7AE5300F608 +:208A2200AA01AE5300F7AE5302F6A0014F494425F5AE53027FAE5005F6AA10AE5005F7AE24 +:208A4200530D7FAE530EA61EF7AE5300F6AA01AE5300F7AE5302F6A0014F494425F5AE5340 +:208A6200027FAE5005F6AA20AE5005F781880F01AE5005F6A4EFAE5005F7AE5005F6887B1B +:208A82000548842408AA20AE5005F72006A4DFAE5005F7AE530D7FAE530EA61EF7AE530018 +:208AA200F6AA01AE5300F7AE5302F6A0014F494425F5AE53027FAE5005F6AA10AE5005F75C +:208AC200AE530D7FAE530EA61EF7AE5300F6AA01AE5300F7AE5302F6A0014F494425F5AE65 +:208AE20053027F7B04486B040C017B01A1082403CC8A72AE5005F6A4EFAE5005F7AE5005C0 +:208B0200F6AA20AE5005F7AE530D7FAE530EA61EF7AE5300F6AA01AE5300F7AE5302F6A00F +:208B2200014F494425F5AE53027FAE5005F6AA10AE5005F7AE530D7FAE530EA60FF7AE53C4 +:208B420000F6AA01AE5300F7AE5302F6A0014F494425F5AE53027FAE5006F6A420A0014FBA +:208B6200499095AE5005F6A4EFAE5005F7909E5B018152030F010F027B016B0308037B030B +:208B82006B01AE5005F6A4EFAE5005F7AE530D7FAE530EA61EF7AE5300F6AA01AE5300F7F0 +:208BA200AE5302F6A0014F494425F5AE53027FAE5005F6AA10AE5005F7AE5006F6A520270E +:208BC200067B01AA016B01AE530D7FAE530EA61EF7AE5300F6AA01AE5300F7AE5302F6A070 +:208BE200014F494425F5AE53027F0C027B02A1082403CC8B7AAE5005F6A4EFAE5005F7AE9A +:208C02005005F60D062708A4DFAE5005F72006AA20AE5005F7AE530D7FAE530EA61EF7AE59 +:208C22005300F6AA01AE5300F7AE5302F6A0014F494425F5AE53027FAE5005F6AA10AE5083 +:208C420005F7AE530D7FAE530EA61EF7AE5300F6AA01AE5300F7AE5302F6A0014F4944258A +:208C6200F5AE53027FAE5005F6A4EFAE5005F7AE5005F6AA20AE5005F77B015B0381520289 +:208C8200A6016B01A6016B02AE5005F6AA10AE5005F7AE5005F6AA20AE5005F7AE5006F647 +:208CA200A5202725A5102721CD8978A6046B013B0013CD8A6F5B014D270F7B0588CD8A6FFF +:208CC2005B014D27040F010F020D0626040D022703CD8A007B015B02815203A6016B01AE60 +:208CE2005005F6AA10AE5005F7AE5005F6AA20AE5005F7AE5006F6A5202735A5102731CDC1 +:208D020089783B0013CD8A6F5B014D27231E067B086B037B036B020A030D022711F65C1F84 +:208D2200068988CD8A6F5B01854D26E720020F010D0926040D012703CD8A004F5B03818862 +:208D4200A6046B01AE5005F6AA10AE5005F7AE5005F6AA20AE5005F7AE5006F6A5202704A7 +:208D6200A5102606A6016B01201CCD89783B0012CD8A6F5B014D270E1E04894B00CD8B7440 +:208D82005B0185F70F01CD8A007B015B018188A6046B01AE5005F6AA10AE5005F7AE5005EB +:208DA200F6AA20AE5005F7AE5006F6A5202704A5102606A6016B012027CD89783B0012CDEA +:208DC2008A6F5B014D27191E04894B01CD8B745B0185F75C894B00CD8B745B0185F70F0130 +:098DE200CD8A007B015B01818058 +:0291CE0000009F +:208DEB00521D1E22A300007B21A2007B20A2002F040F0D2004A6016B0D0D0D27151E225023 +:208E0B004F12216B1B4F12201F186B167B1B6B172008162217181620171616181714161677 +:208E2B0017121E26A300007B25A2007B24A2002E1E7B27406B114F12266B104F12256B0FE8 +:208E4B004F12246B0E1610170B160E170920081626170B16241709160B170716091E078991 +:208E6B0090891E18891E1889CD8E905B0817010D0D270D504F120290974F12019095200219 +:208E8B0016015B1D8152040F020F017B0B484F494D262E160D1E0B905859170D1F0B1E0937 +:208EAB00130D7B08120C7B07120B240D160D1E0B549056170D1F0B20080C017B016B022004 +:208ECB00CA7B026B041E09130D7B08120C7B07120B2513160972F20D7B08120C977B0712B6 +:208EEB000B9517091F07160D1E0B549056170D1F0B7B046B030A040D0326CA1E0916075B13 +:208F0B000481521E1E23A300007B22A2007B21A2002F040F112004A6016B110D1127151EDE +:208F2B0023504F12226B0E4F12211F076B057B0E6B0620081623170716211705160717148B +:208F4B00160517121E27A300007B26A2007B25A2002F040F162004A6016B160D16271E7BCE +:208F6B0028406B1E4F12276B1D4F12266B1C4F12256B1B161D1719161B171720081627178D +:208F8B0019162517171619170B16171E0B8990891E18891E1889CD8FC15B0817017B111841 +:208FAB00164D270D504F120290974F12019095200216015B1E8152125F1F051F03A6206B41 +:208FCB00027B15484F496B0116171E1590585917171F157B036B0F1E04887B076B13840877 +:208FEB001259090F1F047B126B067B0F6B030D01271A7B06AA016B0A7B056B097B046B08F4 +:20900B007B036B0716091705160717031E05131B7B04121A7B031219252B160572F21B7BD9 +:20902B0004121A6B0C7B03121917056B037B0C6B047B18AA0190977B1790957B16977B1581 +:20904B009517171F150A020D022703CC8FCC1E1716155B128152409096905C961C00431F9C +:20906B000B1E0BE603961C00471F151E151F171E171F3F1E3F88E60197844290FF72A900CC +:20908B00021E0BE6031E151F111E111F131E131F191E1988E60397844290FF965C1F1B1EA6 +:2090AB001BF66B1D1E0BF697161590E603429F1B1D1E1BF71E1BF66B1E1E0BE601971615DF +:2090CB0090E602429F1B1E1E1BF79096905C93FE1F1F1E0BE6011E151F211E211F231E239D +:2090EB001F251E2588E60397844272FB1F90FF93FE1F271E0BE6021E151F291E291F2B1EE3 +:20910B002B1F2F1E2F88E60297844272FB2790FF160B1E0BE6021E151F311E311F331E33E7 +:20912B001F351E3588E6019784429F90F71E0B5C1F371E0BE60290971E15E60390421E3735 +:20914B00FF16151E0BE6031E151F3D1E3D1F051E0588F69784429F90F71E155C1F2D1E0B92 +:20916B00E60390971E15E60290421E2DFF1E151C00037F1E0B1C00037F965CE6036B0AE6CF +:20918B00026B09E6016B08F61643170D164572F909173B887B09190F6B3B84190D6B391622 +:1A91AB003BEF021639FFFE16491E4772F93B9F193A979E193995515B40814D +:00000001FF diff --git a/si7005_softi2c/soft_i2c.c b/si7005_softi2c/soft_i2c.c new file mode 100644 index 0000000..c563749 --- /dev/null +++ b/si7005_softi2c/soft_i2c.c @@ -0,0 +1,238 @@ +/* + * soft_i2c.c - functions to work with SW I2C + * + * Copyright 2015 Edward V. Emelianoff + * + * 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 "ports_definition.h" +/* + * In file ports_definition.h should be defined: + * I2C_SDA_PIN, I2C_SDA_PORT, I2C_SCL_PIN and I2C_SCL_PORT + */ + +static U8 addr7r = 0, addr7w = 0; + +extern volatile unsigned long Global_time; + +#define PAUSE(val) do{TIM2_ARRH = 0; TIM2_ARRL = val; TIM2_CR1 |= TIM_CR1_CEN; \ + while(!TIM2_SR1 & TIM_SR1_UIF); TIM2_SR1 = 0;}while(0) + +#define H_DEL PAUSE(30) +#define Q_DEL PAUSE(15) +#define H_SCL PORT(I2C_SCL_PORT, ODR) |= I2C_SCL_PIN +#define L_SCL PORT(I2C_SCL_PORT, ODR) &= ~I2C_SCL_PIN +#define H_SDA PORT(I2C_SDA_PORT, ODR) |= I2C_SDA_PIN +#define L_SDA PORT(I2C_SDA_PORT, ODR) &= ~I2C_SDA_PIN +#define CHK_SDA (PORT(I2C_SDA_PORT, IDR) & I2C_SDA_PIN) +#define CHK_SCL (PORT(I2C_SCL_PORT, IDR) & I2C_SCL_PIN) + +/** + * configure timer for 100kHz speed in standard mode + */ +void i2c_setup(){ + // configure pins: I2C_SDA; I2C_SCL (both opendrain) + PORT(I2C_SDA_PORT, ODR) |= I2C_SDA_PIN; // set to 1 + PORT(I2C_SCL_PORT, ODR) |= I2C_SCL_PIN; + PORT(I2C_SDA_PORT, DDR) |= I2C_SDA_PIN; + PORT(I2C_SCL_PORT, DDR) |= I2C_SCL_PIN; + PORT(I2C_SDA_PORT, CR2) |= I2C_SDA_PIN; + PORT(I2C_SCL_PORT, CR2) |= I2C_SCL_PIN; + // configure TIM2 for delays + TIM2_PSCR = 0; // 16MHz (for working @ 100kHz: 1us \approx 16tacts) + TIM2_CR1 = TIM_CR1_OPM; // one-pulse mode +} + +void i2c_set_addr7(U8 addr){ + addr7w = addr << 1; + addr7r = addr7w | 1; +} + +void SoftStart(){ + H_SCL; + H_DEL; + L_SDA; + H_DEL; + L_SCL; + H_DEL; +} + +void SoftStop(){ + L_SDA; + L_SCL; + H_DEL; + H_SCL; + H_DEL; + H_SDA; +} + +/** + * send 1 byte without start/stop + */ +U8 softi2c_send(U8 data){ + U8 i; + for(i=0; i < 8; i++){ + L_SCL; + if(data & 0x80) + H_SDA; + else + L_SDA; + H_DEL; + H_SCL; + H_DEL; + data <<= 1; + } + // ACK + L_SCL; + H_SDA; + H_DEL; + H_SCL; + Q_DEL; + i = !(CHK_SDA); +// Q_DEL; + L_SCL; +// Q_DEL; + return i; +} +/** + * receive one byte without start/stop + */ +U8 softi2c_receive(U8 ack){ + U8 data = 0, i; + for(i=0; i<8; i++){ + data <<= 1; + L_SCL; + H_DEL; + H_SCL; + if(CHK_SDA) data |= 1; + H_DEL; + } + // prepare for ACK/NACK + L_SCL; + if(ack) L_SDA; + else H_SDA; + H_DEL; + H_SCL; + H_DEL; + L_SCL; + H_SDA; + return data; +} + +/** + * send one byte in 7bit address mode + * @param data - data to write + * @param stop - ==1 to send stop event + * @return I2C_OK if success errcode if fails + */ +i2c_status i2c_7bit_send_onebyte(U8 data, U8 stop){ + i2c_status ret = I2C_LINEBUSY; + U8 err = 1; + H_SCL; H_SDA; + if(!CHK_SDA || !CHK_SCL) goto eotr; + SoftStart(); + ret = I2C_NACK; + if(!softi2c_send(addr7w)) goto eotr; + if(softi2c_send(data)){ + ret = I2C_OK; + err = 0; + } +eotr: + if(stop || err){ + SoftStop(); + } + return ret; +} + +/** + * send datalen bytes over I2C + * @param data - data to write + * @param datalen - amount of bytes in data array + * @param stop - ==1 to send stop event + * return I2C_OK if OK + */ +i2c_status i2c_7bit_send(U8 *data, U8 datalen, U8 stop){ + i2c_status ret = I2C_LINEBUSY; + U8 err = 1; + H_SCL; H_SDA; + if(!CHK_SDA || !CHK_SCL) goto eotr; + SoftStart(); + ret = I2C_NACK; + if(!softi2c_send(addr7w)) goto eotr; + while(datalen--){ + if(!softi2c_send(*data++)) goto eotr; + } + ret = I2C_OK; + err = 0; +eotr: + if(stop || err){ + SoftStop(); + } + return I2C_OK; +} + +/** + * get one byte by I2C + * @param data - data to read (one byte) + * @param wait - leaved for compatibility with HW I2C + * @return I2C_OK if ok || error code + */ +i2c_status i2c_7bit_receive_onebyte(U8 *data, U8 wait){ + i2c_status ret = I2C_NACK; + H_SCL; H_SDA; + (void) wait; + if(!CHK_SDA || !CHK_SCL){ + ret = I2C_LINEBUSY; + goto eotr; + } + SoftStart(); + if(!softi2c_send(addr7r)) goto eotr; + *data = softi2c_receive(0); + ret = I2C_OK; +eotr: + SoftStop(); + return ret; +} + +/** + * receive 2 bytes by I2C + * @param data - data to read (two bytes array, 0 first) + * @param wait - ==1 to wait while LINEBUSY (can send STOP before reading) + * @return I2C_OK if ok || error code + */ +i2c_status i2c_7bit_receive_twobyte(U8 *data, U8 wait){ + i2c_status ret = I2C_NACK; + H_SCL; H_SDA; + (void) wait; + if(!CHK_SDA || !CHK_SCL){ + ret = I2C_LINEBUSY; + goto eotr; + } + SoftStart(); + if(!softi2c_send(addr7r)) goto eotr; + data[0] = softi2c_receive(1); + data[1] = softi2c_receive(0); + ret = I2C_OK; +eotr: + SoftStop(); + return ret; +} + + +INTERRUPT_HANDLER(I2C_IRQHandler, 19){ +} diff --git a/si7005_softi2c/soft_i2c.h b/si7005_softi2c/soft_i2c.h new file mode 100644 index 0000000..f7cd799 --- /dev/null +++ b/si7005_softi2c/soft_i2c.h @@ -0,0 +1,45 @@ +/* + * soft_i2c.h + * + * Copyright 2015 Edward V. Emelianoff + * + * 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 __I2C_H__ +#define __I2C_H__ + +#include "stm8l.h" + +// flags for i2c_state +typedef enum{ + I2C_OK = 0, + I2C_LINEBUSY, + I2C_TMOUT, + I2C_NOADDR, + I2C_NACK, + I2C_HWPROBLEM, +} i2c_status; + +void i2c_setup(); +void i2c_set_addr7(U8 addr); +i2c_status i2c_7bit_send_onebyte(U8 data, U8 stop); +i2c_status i2c_7bit_send(U8 *data, U8 datalen, U8 stop); +i2c_status i2c_7bit_receive_onebyte(U8 *data, U8 wait); +i2c_status i2c_7bit_receive_twobyte(U8 *data, U8 wait); + +#endif // __I2C_H__ diff --git a/si7005_softi2c/uart.c b/si7005_softi2c/uart.c new file mode 100644 index 0000000..9da5b2d --- /dev/null +++ b/si7005_softi2c/uart.c @@ -0,0 +1,169 @@ +/* + * blinky.c + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 "ports_definition.h" +#include "uart.h" +#include "interrupts.h" + +U8 UART_rx[UART_BUF_LEN]; // cycle buffer for received data +U8 UART_rx_start_i = 0; // started index of received data (from which reading starts) +U8 UART_rx_cur_i = 0; // index of current first byte in rx array (to which data will be written) + +/** + * Send one byte through UART + * @param byte - data to send + */ +void UART_send_byte(U8 byte){ + while(!(UART2_SR & UART_SR_TXE)); // wait until previous byte transmitted + UART2_DR = byte; +} + +void uart_write(char *str){ + while(*str){ + while(!(UART2_SR & UART_SR_TXE)); + UART2_CR2 |= UART_CR2_TEN; + UART2_DR = *str++; + } +} + +/** + * Read one byte from Rx buffer + * @param byte - where to store readed data + * @return 1 in case of non-empty buffer + */ +U8 UART_read_byte(U8 *byte){ + if(UART_rx_start_i == UART_rx_cur_i) // buffer is empty + return 0; + *byte = UART_rx[UART_rx_start_i++]; + check_UART_pointer(UART_rx_start_i); + return 1; +} + +void printUint(U8 *val, U8 len){ + unsigned long Number = 0; + U8 i = len; + char ch; + U8 decimal_buff[12]; // max len of U32 == 10 + \n + \0 + if(len > 4 || len == 3 || len == 0) return; + for(i = 0; i < 12; i++) + decimal_buff[i] = 0; + decimal_buff[10] = '\n'; + ch = 9; + switch(len){ + case 1: + Number = *((U8*)val); + break; + case 2: + Number = *((U16*)val); + break; + case 4: + Number = *((unsigned long*)val); + break; + } + do{ + i = Number % 10L; + decimal_buff[ch--] = i + '0'; + Number /= 10L; + }while(Number && ch > -1); + uart_write((char*)&decimal_buff[ch+1]); +} + +/** + * print signed long onto terminal + * max len = 10 symbols + 1 for "-" + 1 for '\n' + 1 for 0 = 13 + */ +void print_long(long Number){ + U8 i, L = 0; + char ch; + char decimal_buff[12]; + decimal_buff[11] = 0; + ch = 11; + if(Number < 0){ + Number = -Number; + L = 1; + } + do{ + i = Number % 10L; + decimal_buff[--ch] = i + '0'; + Number /= 10L; + }while(Number && ch > 0); + if(ch > 0 && L) decimal_buff[--ch] = '-'; + uart_write(&decimal_buff[ch]); +} + +U8 readInt(int *val){ + unsigned long T = Global_time; + unsigned long R = 0; + int readed; + U8 sign = 0, rb, ret = 0, bad = 0; + do{ + if(!UART_read_byte(&rb)) continue; + if(rb == '-' && R == 0){ // negative number + sign = 1; + continue; + } + if(rb < '0' || rb > '9') break; // number ends with any non-digit symbol that will be omitted + ret = 1; // there's at least one digit + R = R * 10L + rb - '0'; + if(R > 0x7fff){ // bad value + R = 0; + bad = 0; + } + }while(Global_time - T < 10000); // wait no longer than 10s + if(bad || !ret) return 0; + readed = (int) R; + if(sign) readed *= -1; + *val = readed; + return 1; +} + +void error_msg(char *msg){ + uart_write("\nERROR: "); + uart_write(msg); + UART_send_byte('\n'); +} + +U8 U8toHEX(U8 val){ + val &= 0x0f; + if(val < 10) val += '0'; + else val += 'a' - 10; + return val; +} + +void printUHEX(U8 val){ + uart_write("0x"); + UART_send_byte(U8toHEX(val>>4)); // MSB + UART_send_byte(U8toHEX(val)); // LSB +} + +void uart_init(){ + // PD5 - UART2_TX + PORT(UART_PORT, DDR) |= UART_TX_PIN; + PORT(UART_PORT, CR1) |= UART_TX_PIN; +// Configure UART + // 8 bit, no parity, 1 stop (UART_CR1/3 = 0 - reset value) + // 57600 on 16MHz: BRR1=0x11, BRR2=0x06 + UART2_BRR1 = 0x11; UART2_BRR2 = 0x06; + UART2_CR2 = UART_CR2_TEN | UART_CR2_REN | UART_CR2_RIEN; // Allow RX/TX, generate ints on rx +} + + diff --git a/si7005_softi2c/uart.h b/si7005_softi2c/uart.h new file mode 100644 index 0000000..cfd9d6e --- /dev/null +++ b/si7005_softi2c/uart.h @@ -0,0 +1,45 @@ +/* + * blinky.h + * + * Copyright 2014 Edward V. Emelianoff + * + * 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 __MAIN_H__ +#define __MAIN_H__ + +extern volatile unsigned long Global_time; // global time in ms + +#define UART_BUF_LEN 8 // max 7 bytes transmited in on operation + +extern U8 UART_rx[]; +extern U8 UART_rx_start_i; +extern U8 UART_rx_cur_i; + + +void UART_send_byte(U8 byte); +void uart_write(char *str); +void printUint(U8 *val, U8 len); +void print_long(long Number); +void error_msg(char *msg); +void uart_init(); +U8 UART_read_byte(U8 *byte); +void printUHEX(U8 val); + +#define check_UART_pointer(x) do{if(x == UART_BUF_LEN) x = 0;}while(0) + +#endif // __MAIN_H__ diff --git a/stm8l.h b/stm8l.h index 103de46..a66b643 100644 --- a/stm8l.h +++ b/stm8l.h @@ -492,6 +492,42 @@ typedef unsigned long U32; // CCR REGISTER: bits 3&5 should be 1 if you wanna change EXTI_CRx #define CCR *(unsigned char*)0x7F0A +/* -------------------- OPTION BYTES -------------------- */ +#if defined STM8S105 +// readout protection +#define OPT0 *(unsigned char*)0x4800 +// user boot code +#define OPT1 *(unsigned char*)0x4801 +#define NOPT1 *(unsigned char*)0x4802 +// alternate functions remapping +// | AFR7 | ... | AFR0 | +// AFR7 - PD4 = BEEP; AFR6 - PB4/PB5 = I2C; AFR5 - PB0..3 - TIM1 +// AFR4 - PD7 = TIM1_CH4; AFR3 - PD0 = TIM1_BKIN +// AFR2 - PD0 = CLK_CCO; AFR1 - PA3 = TIM3_CH1, PD2 = TIM2_CH3 +// AFR0 - PD3 = ADC_ETR +#define OPT2 *(unsigned char*)0x4803 +#define NOPT2 *(unsigned char*)0x4804 +// trim, watchdog +#define OPT3 *(unsigned char*)0x4805 +#define NOPT3 *(unsigned char*)0x4806 +// extclc, awu +#define OPT4 *(unsigned char*)0x4807 +#define NOPT4 *(unsigned char*)0x4808 +// HSE stab time +#define OPT5 *(unsigned char*)0x4809 +#define NOPT5 *(unsigned char*)0x480a +// none +#define OPT6 *(unsigned char*)0x480b +#define NOPT6 *(unsigned char*)0x480c +// none +#define OPT7 *(unsigned char*)0x480d +#define NOPT7 *(unsigned char*)0x480e +// bootloader opt byte +#define OPTBL *(unsigned char*)0x487e +#define NOPTBL *(unsigned char*)0x487f + +#endif + #endif // __STM8L_H__ // #define *(unsigned char*)0x