Add i2c_stts75_sensor example.

Thanks Thomas Otto <tommi@viadmin.org> for the patch!
This commit is contained in:
Uwe Hermann 2010-03-05 22:35:29 +01:00
parent f514162134
commit 46e5ed202a
8 changed files with 599 additions and 2 deletions

View File

@ -25,7 +25,7 @@ ifneq ($(V),1)
Q := @ Q := @
endif endif
all: stm32-h103 mb525 all: stm32-h103 mb525 other
stm32-h103: stm32-h103:
@printf " BUILD examples/stm32-h103\n" @printf " BUILD examples/stm32-h103\n"
@ -35,11 +35,17 @@ mb525:
@printf " BUILD examples/mb525\n" @printf " BUILD examples/mb525\n"
$(Q)$(MAKE) -C mb525 $(Q)$(MAKE) -C mb525
other:
@printf " BUILD examples/other\n"
$(Q)$(MAKE) -C other
clean: clean:
@printf " CLEAN examples/stm32-h103\n" @printf " CLEAN examples/stm32-h103\n"
$(Q)$(MAKE) -C stm32-h103 clean $(Q)$(MAKE) -C stm32-h103 clean
@printf " CLEAN examples/mb525\n" @printf " CLEAN examples/mb525\n"
$(Q)$(MAKE) -C mb525 clean $(Q)$(MAKE) -C mb525 clean
@printf " CLEAN examples/other\n"
$(Q)$(MAKE) -C other clean
.PHONY: stm32-h103 mb525 clean .PHONY: stm32-h103 mb525 other clean

39
examples/other/Makefile Normal file
View File

@ -0,0 +1,39 @@
##
## This file is part of the libopenstm32 project.
##
## Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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 3 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, see <http://www.gnu.org/licenses/>.
##
# Do not print "Entering directory ...".
MAKEFLAGS += --no-print-directory
# Be silent per default, but 'make V=1' will show all compiler calls.
ifneq ($(V),1)
Q := @
endif
all: i2c_stts75_sensor
i2c_stts75_sensor:
@printf " BUILD i2c_stts75_sensor\n"
$(Q)$(MAKE) -C i2c_stts75_sensor
clean:
@printf " CLEAN i2c_stts75_sensor\n"
$(Q)$(MAKE) -C i2c_stts75_sensor clean
.PHONY: i2c_stts75_sensor clean

View File

@ -0,0 +1,95 @@
##
## This file is part of the libopenstm32 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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 3 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, see <http://www.gnu.org/licenses/>.
##
BINARY = i2c_stts75_sensor
# PREFIX ?= arm-none-eabi
PREFIX ?= arm-elf
CC = $(PREFIX)-gcc
LD = $(PREFIX)-ld
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
# Uncomment this line if you want to use the installed (not local) library.
# TOOLCHAIN_DIR = `dirname \`which $(CC)\``/../$(PREFIX)
TOOLCHAIN_DIR = ../../..
CFLAGS = -O0 -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include -fno-common \
-mcpu=cortex-m3 -mthumb
LDSCRIPT = $(BINARY).ld
LDFLAGS = -L$(TOOLCHAIN_DIR)/lib -T$(LDSCRIPT) -nostartfiles
OBJS = $(BINARY).o stts75.o
OPENOCD_BASE = /usr
OPENOCD = $(OPENOCD_BASE)/bin/openocd
OPENOCD_SCRIPTS = $(OPENOCD_BASE)/share/openocd/scripts
OPENOCD_FLASHER = $(OPENOCD_SCRIPTS)/interface/jtagkey.cfg
OPENOCD_BOARD = $(OPENOCD_SCRIPTS)/target/stm32.cfg
# Be silent per default, but 'make V=1' will show all compiler calls.
ifneq ($(V),1)
Q := @
NULL := 2>/dev/null
endif
all: images
images: $(BINARY)
@printf " OBJCOPY $(BINARY).bin\n"
$(Q)$(OBJCOPY) -Obinary $(BINARY) $(BINARY).bin
@printf " OBJCOPY $(BINARY).hex\n"
$(Q)$(OBJCOPY) -Oihex $(BINARY) $(BINARY).hex
@printf " OBJCOPY $(BINARY).srec\n"
$(Q)$(OBJCOPY) -Osrec $(BINARY) $(BINARY).srec
@printf " OBJDUMP $(BINARY).list\n"
$(Q)$(OBJDUMP) -S $(BINARY) > $(BINARY).list
$(BINARY): $(OBJS) $(LDSCRIPT)
@printf " LD $(subst $(shell pwd)/,,$(@))\n"
$(Q)$(LD) $(LDFLAGS) -o $(BINARY) $(OBJS) -lopenstm32
%.o: %.c Makefile
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
clean:
@printf " CLEAN $(subst $(shell pwd)/,,$(OBJS))\n"
$(Q)rm -f *.o
@printf " CLEAN $(BINARY)\n"
$(Q)rm -f $(BINARY)
@printf " CLEAN $(BINARY).bin\n"
$(Q)rm -f $(BINARY).bin
@printf " CLEAN $(BINARY).hex\n"
$(Q)rm -f $(BINARY).hex
@printf " CLEAN $(BINARY).srec\n"
$(Q)rm -f $(BINARY).srec
@printf " CLEAN $(BINARY).list\n"
$(Q)rm -f $(BINARY).list
flash: images
@printf " FLASH $(BINARY).bin\n"
@# IMPORTANT: Don't use "resume", only "reset" will work correctly!
$(Q)$(OPENOCD) -s $(OPENOCD_SCRIPTS) \
-f $(OPENOCD_FLASHER) \
-f $(OPENOCD_BOARD) \
-c "init" -c "reset halt" \
-c "flash write_image erase $(BINARY).hex" \
-c "reset" \
-c "shutdown" $(NULL)
.PHONY: images clean

View File

@ -0,0 +1,49 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This example program sends some characters on USART1.
Afterwards it connects to an STTS75 sensor (ST LM75 compatible)
at adress A0/1/2=0 and sets reverse polarity, 26 degree Tos and Thyst.
It reads out the temperature and submits the temperature over USART1 in
binary format (ASCII 0/1).
The terminal settings for the receiving device/PC are 115200 8n1.
Building
--------
$ make
Running 'make' on the top-level libopenstm32 directory will automatically
also build this example. Or you can build the library "manually" and
then run 'make' in this directory.
You may want to override the toolchain (e.g., arm-elf or arm-none-eabi):
$ PREFIX=arm-none-eabi make
For a more verbose build you can use
$ make V=1
Flashing
--------
You can flash the generated code using OpenOCD:
$ make flash
Or you can do the same manually via:
$ openocd -f interface/jtagkey-tiny.cfg -f target/stm32.cfg
$ telnet localhost 4444
> reset halt
> flash write_image erase i2c_stts75_sensor.hex
> reset
Replace the "jtagkey-tiny.cfg" with whatever JTAG device you are using, and/or
replace "stm.cfg" with your respective config file.

View File

@ -0,0 +1,152 @@
/*
* This file is part of the libopenstm32 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <libopenstm32/rcc.h>
#include <libopenstm32/flash.h>
#include <libopenstm32/gpio.h>
#include <libopenstm32/usart.h>
#include <libopenstm32/i2c.h>
#include "stts75.h"
/* Set STM32 to 72 MHz. */
void clock_setup(void)
{
rcc_clock_setup_in_hse_8mhz_out_72mhz();
}
void usart_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, USART1EN);
/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
/* Setup UART parameters. */
usart_set_baudrate(USART1, 115200);
usart_set_databits(USART1, 8);
usart_set_stopbits(USART1, USART_STOPBITS_1);
usart_set_mode(USART1, USART_MODE_TX_RX);
usart_set_parity(USART1, USART_PARITY_NONE);
usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART1);
}
void gpio_setup(void)
{
/* Enable GPIOB clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, IOPBEN);
/* Set GPIO6/7 (in GPIO port B) to 'output push-pull' for the LEDs. */
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO6);
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO7);
}
void i2c_setup(void)
{
/* Enable clocks for I2C2 and AFIO. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, I2C2EN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, AFIOEN);
/* Set alternate functions for the SCL and SDA pins of I2C2. */
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,
GPIO_I2C2_SCL | GPIO_I2C2_SDA);
/* Disable the I2C before changing any configuration. */
i2c_peripheral_disable(I2C2);
/* APB1 is running at 36MHz. */
i2c_set_clock_frequency(I2C2, I2C_CR2_FREQ_36MHZ);
/* 400KHz - I2C Fast Mode */
i2c_set_fast_mode(I2C2);
/*
* fclock for I2C is 36MHz APB2 -> cycle time 28ns, low time at 400KHz
* incl trise -> Thigh= 1600ns; CCR= tlow/tcycle= 0x1C,9;
* datasheet suggests 0x1e.
*/
i2c_set_ccr(I2C2, 0x1e);
/*
* fclock for I2C is 36MHz -> cycle time 28ns, rise time for
* 400KHz => 300ns and 100KHz => 1000ns; 300ns/28ns = 10;
* incremented by 1 -> 11.
*/
i2c_set_trise(I2C2, 0x0b);
/*
* This is our slave address - needed only if we want to receive from
* other masters.
*/
i2c_set_own_7bit_slave_address(I2C2, 0x32);
/* If everything is configured -> enable the peripheral. */
i2c_peripheral_enable(I2C2);
}
int main(void)
{
int i = 0;
u16 temperature;
clock_setup();
gpio_setup();
usart_setup();
i2c_setup();
gpio_clear(GPIOB, GPIO7); /* LED1 on */
gpio_set(GPIOB, GPIO6); /* LED2 off */
/* Send a message on USART1. */
usart_send(USART1, 's');
usart_send(USART1, 't');
usart_send(USART1, 'm');
usart_send(USART1, '\r');
usart_send(USART1, '\n');
stts75_write_config(I2C2, STTS75_SENSOR0);
stts75_write_temp_os(I2C2, STTS75_SENSOR0, 0x1a00); /* 26 degrees */
stts75_write_temp_hyst(I2C2, STTS75_SENSOR0, 0x1a00);
temperature = stts75_read_temperature(I2C2, STTS75_SENSOR0);
/* Send the temperature as binary over USART1. */
for (i = 15; i >= 0 ; i--) {
if (temperature & (1 << i))
usart_send(USART1, '1');
else
usart_send(USART1, '0');
}
usart_send(USART1, '\r');
usart_send(USART1, '\n');
gpio_clear(GPIOB, GPIO6); /* LED2 on */
while(1); /* Halt. */
return 0;
}

View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopenstm32 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for an STM32F103RBT6 board (128K flash, 20K RAM). */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
/* Include the common ld script from libopenstm32. */
INCLUDE libopenstm32.ld

View File

@ -0,0 +1,186 @@
/*
* This file is part of the libopenstm32 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <libopenstm32/i2c.h>
#include "stts75.h"
void stts75_write_config(u32 i2c, u8 sensor)
{
u32 tempreg;
/* Send START condition. */
i2c_send_start(i2c);
/* Waiting for START is send and switched to master mode. */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
/* Send destination address. */
i2c_send_7bit_address(i2c, sensor, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
tempreg = I2C_SR2(i2c);
/* Sending the data. */
i2c_send_data(i2c, 0x1); /* stts75 config register */
while (!(I2C_SR1(i2c) & I2C_SR1_BTF)); /* Await ByteTransferedFlag. */
i2c_send_data(i2c, 0x4); /* pol reverse - LED glows if temp is below Tos/Thyst */
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));
/* Send STOP condition. */
i2c_send_stop(i2c);
}
void stts75_write_temp_os(u32 i2c, u8 sensor, u16 temp_os)
{
u32 tempreg;
/* Send START condition. */
i2c_send_start(i2c);
/* Waiting for START is send and switched to master mode. */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
/* Send destination address. */
i2c_send_7bit_address(i2c, sensor, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
tempreg = I2C_SR2(i2c);
/* Sending the data. */
i2c_send_data(i2c, 0x3); /* OvertemperatureShutdown register */
while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
i2c_send_data(i2c, (u8)(temp_os >> 8)); /* MSB */
while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
i2c_send_data(i2c, (u8)(temp_os & 0xff00)); /* LSB */
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE))); /* After the last byte we have to wait for TxE too. */
/* Send STOP condition. */
i2c_send_stop(i2c);
}
void stts75_write_temp_hyst(u32 i2c, u8 sensor, u16 temp_hyst)
{
u32 tempreg;
/* Send START condition. */
i2c_send_start(i2c);
/* Waiting for START is send and therefore switched to master mode. */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
/* Say to what address we want to talk to. */
i2c_send_7bit_address(i2c, sensor, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
tempreg = I2C_SR2(i2c);
/* Sending the data. */
i2c_send_data(i2c, 0x2); /* TemperatureHysteresis register */
while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
i2c_send_data(i2c, (u8)(temp_hyst >> 8)); /* MSB */
while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
i2c_send_data(i2c, (u8)(temp_hyst & 0xff00)); /* LSB */
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE))); /* After the last byte we have to wait for TxE too. */
/* Send STOP condition. */
i2c_send_stop(i2c);
}
u16 stts75_read_temperature(u32 i2c, u8 sensor)
{
u32 tempreg;
u16 temperature;
/* Send START condition. */
i2c_send_start(i2c);
/* Waiting for START is send and switched to master mode. */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
/* Say to what address we want to talk to. */
/* Yes, WRITE is correct - for selecting register in STTS75. */
i2c_send_7bit_address(i2c, sensor, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
tempreg = I2C_SR2(i2c);
i2c_send_data(i2c, 0x0); /* temperature register */
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF|I2C_SR1_TxE)));
/*
* Now we transferred that we want to ACCESS the temperature register.
* Now we send another START condition (repeated START) and then
* transfer the destination but with flag READ.
*/
/* Send START condition. */
i2c_send_start(i2c);
/* Waiting for START is send and switched to master mode. */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
/* Say to what address we want to talk to. */
i2c_send_7bit_address(i2c, sensor, I2C_READ);
/* 2-byte receive is a special case. See datasheet POS bit. */
I2C_CR1(i2c) |= (I2C_CR1_POS | I2C_CR1_ACK);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
tempreg = I2C_SR2(i2c);
/* Cleaning I2C_SR1_ACK. */
I2C_CR1(i2c) &= ~ I2C_CR1_ACK;
/* Now the slave should begin to send us the first byte. Await BTF. */
while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
temperature = (u16)(I2C_DR(i2c) << 8); /* MSB */
/*
* Yes they mean it: we have to generate the STOP condition before
* saving the 1st byte.
*/
I2C_CR1(i2c) |= I2C_CR1_STOP;
temperature |= I2C_DR(i2c); /* LSB */
/* Original state. */
I2C_CR1(i2c) &= ~I2C_CR1_POS;
return temperature;
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of the libopenstm32 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef STTS75_H
#define STTS75_H
#include <stdint.h>
#define STTS75_SENSOR0 0x48
#define STTS75_SENSOR1 0x49
#define STTS75_SENSOR2 0x4a
#define STTS75_SENSOR3 0x4b
#define STTS75_SENSOR4 0x4c
#define STTS75_SENSOR5 0x4d
#define STTS75_SENSOR6 0x4e
#define STTS75_SENSOR7 0x4f
void stts75_write_config(u32 i2c, u8 sensor);
void stts75_write_temp_os(u32 i2c, u8 sensor, u16 temp_os);
void stts75_write_temp_hyst(u32 i2c, u8 sensor, u16 temp_hyst);
u16 stts75_read_temperature(u32 i2c, u8 sensor);
#endif