I'm trying to make an i2c scanner (just like the arduino one) for the STM8S005K6 but I can't seem to even generate a start condition for the communication to begin.
I have to say, I've never used STM8 or the STVD IDE and I'm learning by myself with the limited information that is available.
I've looked in two or three forums on how to use I2C, but there is something on my particular case that is stopping me from getting it to work. I have connected to my I2C bus a BMP180 (address 0x77).
The code execution always gets stuck on while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT))
.
Here is the code:
/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
#include "stm8s.h"
#include <string.h>
void setup(void);
void __delay_ms(unsigned int);
void UART2_SendString(char *, int );
char* itoa(int num, char* str, int base);
void reverse(char s[]);
main(){
setup();
I2C_DeInit();
I2C_Init(100000, 0x00, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, (CLK_GetClockFreq() / 1000000));
I2C_Cmd(ENABLE);
UART2_SendString("STM8 INIT OK!\n\r", 20);
while (1){
char error, address, tmp[20];
int nDevices;
UART2_SendString("Scanning...\n\r", 20);
nDevices = 0;
for(address = 1; address < 127; address++) {
UART2_SendString("START\n\r", 10);
I2C_GenerateSTART(ENABLE);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
UART2_SendString("ADDR\n\r", 10);
I2C_Send7bitAddress(address, I2C_DIRECTION_TX);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
UART2_SendString("STOP\n\r", 10);
I2C_GenerateSTOP(ENABLE);
error = I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
if (error == SET) {
UART2_SendString("I2C device found at address 0x", 40);
if (address < 16)
UART2_SendString("0", 10);
itoa(address, tmp, 16);
UART2_SendString(tmp, 10);
UART2_SendString("\n\r", 10);
nDevices++;
}
else if (error == 4) {
UART2_SendString("Unknown error at address 0x", 40);
if (address < 16)
UART2_SendString("0", 10);
itoa(address, tmp, 16);
UART2_SendString(tmp, 10);
UART2_SendString("\n\r", 10);
}
}
if (nDevices == 0)
UART2_SendString("No I2C devices found\n\r", 40);
else
UART2_SendString("done\n\r", 10);
__delay_ms(5000); // wait 5 seconds for next scan
}
}
void setup(void){
CLK_DeInit();
/* Configure the Fcpu to DIV1*/
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
/* Configure the HSI prescaler to the optimal value */
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
/* Configure the system clock to use HSI clock source and to run at 16Mhz */
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART2, ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER3, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, ENABLE);
TIM4_DeInit();
/* Configure Timer4 to prescaler 1:16 */
TIM4_PrescalerConfig(TIM4_PRESCALER_16, TIM4_PSCRELOADMODE_UPDATE);
/* Make Timer4 reset every 99 counts (100us) */
TIM4_SetAutoreload(99);
UART2_DeInit();
UART2_Init(9600, UART2_WORDLENGTH_8D, UART2_STOPBITS_1, UART2_PARITY_NO, UART2_SYNCMODE_CLOCK_DISABLE, UART2_MODE_TX_ENABLE);
GPIO_DeInit(GPIOB);
GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_FAST);
GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_FAST);
GPIO_DeInit(GPIOD);
GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_SLOW);
}
void __delay_ms(unsigned int period){
unsigned int m = 0, u = 0;
TIM4_SetCounter(0); // Reset counter for good measure
TIM4_Cmd(ENABLE); // Enable Timer4
for (m = 0; m <= period; m++){ // Counts miliseconds
for (u = 0; u <= 10; u++){ //Counts every 100 microseconds
while(TIM4_GetFlagStatus(TIM4_FLAG_UPDATE) == RESET); //Wait for Timer4 update flag to be set
TIM4_ClearFlag(TIM4_FLAG_UPDATE); // Clear update flag
}
}
TIM4_Cmd(DISABLE); // Disable Timer4 when done
}
void UART2_SendString(char *str, int max_length){
int i = 0;
for (i = 0; i < max_length && str[i] != '\0'; i++) {
GPIO_WriteHigh(GPIOD, GPIO_PIN_4);
while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET);
UART2_SendData8(str[i]);
GPIO_WriteLow(GPIOD, GPIO_PIN_4);
}
GPIO_WriteLow(GPIOD, GPIO_PIN_4);
}
char* itoa(int num, char* str, int base){
int i = 0;
bool isNegative = 0;
/* Handle 0 explicitly, otherwise empty string is printed for 0 */
if (num == 0)
{
str[i++] = '0';
str[i] = '\0';
return str;
}
// In standard itoa(), negative numbers are handled only with
// base 10. Otherwise numbers are considered unsigned.
if (num < 0 && base == 10)
{
isNegative = 1;
num = -num;
}
// Process individual digits
while (num != 0)
{
int rem = num % base;
str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
num = num/base;
}
// If number is negative, append '-'
if (isNegative)
str[i++] = '-';
str[i] = '\0'; // Append string terminator
// Reverse the string
reverse(str);
return str;
}
void reverse(char s[]){
int i, j;
char c;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
I'm using the STM8S_StdPeriph_Lib from the ST Official Website.