Перейти к содержанию
    

Stm32f100 и i2c

Доброго времени суток!

Возникла задача, необходимо связать stm32 связать с мультиплексорной платой ADG728, который связывается при помощи I2C, код написан, но на осциллографе я вижу только подъем с нуля на единицу, никаких импульсов не вижу

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"

//----------------
#include "stm32f10x_i2c.h"

GPIO_InitTypeDef gpio;
I2C_InitTypeDef i2c;
#define TIMER_PRESCALER		720
#define EXT_TIM_PULSE 			150
#define TIM_PULSE		 50

uint16_t previousState;
GPIO_InitTypeDef port;
TIM_TimeBaseInitTypeDef timer;
TIM_OCInitTypeDef timerPWM;
uint16_t buttonPreviousState;
GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitStructure;
void I2C_init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_OwnAddress1 = 1;
I2C_InitStructure.I2C_Ack = I2C_Ack_Disable;//Enable
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
I2C_AcknowledgeConfig(I2C1, ENABLE);
}

void I2C_single_write(uint8_t HW_address, uint8_t addr, uint8_t data)
{
I2C_GenerateSTART(I2C1, ENABLE);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, HW_address, I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, data);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
}

uint8_t I2C_single_read(uint8_t HW_address, uint8_t addr)
{
uint8_t data;
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1, ENABLE);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, HW_address, I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTART(I2C1, ENABLE);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, HW_address, I2C_Direction_Receiver);
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
return data;
}

void delay(int a)
{
int i = 0;
int f = 0;
while(f < a)
{
	while(i<60)
		{i++;}
	f++;
}
}

int main()
{
uint8_t single_data_read = 0;

I2C_init();
delay(500);
	I2C_StretchClockCmd(I2C1, ENABLE);

I2C_single_write(0xA0, 0x00, 0x15);
delay(500);

single_data_read = I2C_single_read(0xA0, 0x03);

while(1);
}

Будьте добры, дайте советов, проект горит, спасибо

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Будьте добры, дайте советов, проект горит, спасибо

Если проект горит, я бы не связывался с аппаратным I2C у STM32 - это очень странный зверь.

Лучше сделайте ногодрыгом - это проще и надёжнее. Примеров кода в тырнетах масса: i2c bit banging code.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если проект горит, я бы не связывался с аппаратным I2C у STM32 - это очень странный зверь.

Лучше сделайте ногодрыгом - это проще и надёжнее. Примеров кода в тырнетах масса: i2c bit banging code.

Данный мультиплексор работает ведь только с i2c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если проект горит, я бы не связывался с аппаратным I2C у STM32 - это очень странный зверь.

Кривоватый конечно, но работает. Если может помочь код, не использующий либы, могу поделиться работающим примером для EEPROM (STM32F103)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Данный мультиплексор работает ведь только с i2c

Неужели вы не в курсе, что такое "i2c через ногодрыг". Лучше почитайте про это, в вашей ситуации это будет очень полезное знание, ИМХО.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кривоватый конечно, но работает. Если может помочь код, не использующий либы, могу поделиться работающим примером для EEPROM (STM32F103)

было бы замечательно, спасибо

 

Неужели вы не в курсе, что такое "i2c через ногодрыг". Лучше почитайте про это, в вашей ситуации это будет очень полезное знание, ИМХО.

Спасибо, обязательно почитаю, новичок еще в этом деле

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

было бы замечательно, спасибо

Обманул, для 103-го дома не оказалось. Есть только для F4xx и для F030, но они вроде очень похожи. Посмотрите...

f030_i2c.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго времени суток!

Возникла задача, необходимо связать stm32 связать с мультиплексорной платой ADG728, который связывается при помощи I2C, код написан, но на осциллографе я вижу только подъем с нуля на единицу, никаких импульсов не вижу

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

Для i2c необходимо сконфигурировать пины в режиме "альтернативная функция, открытый сток", ни в коем случае не пушпулл, а то i2c не будет управлять пинами. Кстати, в мануале в разделе 9.1.11 написано, как следует конфигурировать GPIO для каждой функции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот инициализация для 103-го камня, кривовато, но может поможет:

void i2c_init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    I2C_InitTypeDef  I2C_InitStructure;

    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

        /* I2C1 SDA and SCL configuration */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

     /* I2C1 configuration */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 400000;//ClockSpeed;
    I2C_Cmd(I2C1, ENABLE);
    I2C_Init(I2C1, &I2C_InitStructure);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для i2c необходимо сконфигурировать пины в режиме "альтернативная функция, открытый сток", ни в коем случае не пушпулл, а то i2c не будет управлять пинами. Кстати, в мануале в разделе 9.1.11 написано, как следует конфигурировать GPIO для каждой функции.

 

Все равно никакого эффека

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто нибудь реализовал i2c через i2c bit banging code? Не могли бы скинуть примеры

Вот тут нечто похожее на вменяемый код. И протестировано должно быть, раз называется примером.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ногодрыгом делать i2c это моветон. Я делал как полингом, так и по прерыванию.

unsigned char I2c_Start (I2C_TypeDef* I2Cx)
{
u16 cnt = maxcnt;
if (I2Cx->SR2&I2C_SR2_BUSY) return I2C_BUS_BUSY;
I2Cx->CR1 |= I2C_CR1_START;
while ((I2Cx->SR1 & I2C_SR1_SB) == 0)
{
	cnt--;
	if (cnt == 0) return I2C_BUS_BUSY;
}
return 0;
}

void I2c_ReStart (I2C_TypeDef* I2Cx)
{
I2Cx->CR1 |= I2C_CR1_START;
while (!(I2Cx->SR1 & I2C_SR1_SB));
}

unsigned char I2c_WriteAddress (I2C_TypeDef* I2Cx, unsigned char i2c_address)
{
u16 cnt = maxcnt;
I2Cx->DR = i2c_address;
while (!(I2Cx->SR1 & (I2C_SR1_ADDR|I2C_SR1_ARLO|I2C_SR1_AF)))//stuck here sometimes
{
	cnt--;
	if (cnt == 0) return I2C_NOACK;
}
if (I2Cx->SR1&(I2C_SR1_ARLO|I2C_SR1_AF)) return I2C_NOACK;
(void) I2Cx->SR1;
(void) I2Cx->SR2;
if (i2c_address&1) while (!(I2Cx->SR1 & I2C_SR1_RXNE));
return 0;
}

void I2c_WriteByte (I2C_TypeDef* I2Cx, unsigned char data)
{
I2Cx->DR = data;
while (!(I2Cx->SR1 & I2C_SR1_BTF));
}

unsigned char I2c_ReadByte (I2C_TypeDef* I2Cx)
{
while((I2Cx->SR1 & I2C_SR1_RXNE)==0);   // wait data
I2Cx->SR1;
 I2Cx->SR2;
return I2Cx->DR;
}

unsigned char I2c_Stop (I2C_TypeDef* I2Cx)
{	
I2Cx->CR1 |= I2C_CR1_STOP;
while (I2Cx->SR2&I2C_SR2_BUSY);
return I2C_OK;
}

void I2c_ACK (I2C_TypeDef* I2Cx)
{
I2Cx->CR1 |= I2C_CR1_ACK;
}

void I2c_NACK (I2C_TypeDef* I2Cx)
{
I2Cx->CR1 &= ~I2C_CR1_ACK;
}

/* Reads Page with 1-byte pointer */
unsigned char I2c_Read_Page (I2C_TypeDef* I2Cx, unsigned char I2c_Address, unsigned char Reg, unsigned char * buffer, unsigned char Len)
{
I2c_ACK(I2Cx);
if (I2c_Start(I2Cx)) return I2C_BUS_BUSY;
if (I2c_WriteAddress(I2Cx, I2c_Address)) return I2C_NOACK; 
I2c_WriteByte(I2Cx, Reg);
I2c_ReStart(I2Cx);
I2c_WriteAddress(I2Cx, I2c_Address|1);	
while (Len>1)
{		
	I2c_ACK(I2Cx);
	* buffer++ = I2c_ReadByte(I2Cx);
	Len--;
}
I2Cx->CR1&=~I2C_CR1_POS;
I2Cx->CR1 |= I2C_CR1_STOP;
* buffer++ = I2c_ReadByte(I2Cx);
//I2Cx->CR1 |= I2C_CR1_STOP;	
I2c_NACK(I2Cx);	
return I2C_OK;
}

unsigned char I2c_Write_Page (I2C_TypeDef* I2Cx, unsigned char I2c_Address, unsigned char Reg, unsigned char * buffer, unsigned char Len)
{
I2c_ACK(I2Cx);
if (I2c_Start(I2Cx)) return I2C_BUS_BUSY;
if (I2c_WriteAddress(I2Cx, I2c_Address)) return I2C_NOACK;
I2c_WriteByte(I2Cx, Reg);
while (Len--)
	I2c_WriteByte(I2Cx, * buffer++);
I2c_Stop(I2Cx);
return I2C_OK;
}


unsigned char I2c_Write_Register (I2C_TypeDef* I2Cx, unsigned char I2c_Address, unsigned char Reg, unsigned char data)
{
if (I2c_Start(I2Cx)) return I2C_BUS_BUSY;
if (I2c_WriteAddress(I2Cx, I2c_Address)) return I2C_NOACK;
I2c_WriteByte(I2Cx, Reg);
I2c_WriteByte(I2Cx, data);
I2c_Stop(I2Cx);
return I2C_OK;
}

I2C_RESULT CheckI2C (I2C_TypeDef* I2Cx)
{
if (I2Cx->SR2&I2C_SR2_BUSY) return I2C_BUS_BUSY;
return I2C_OK;
}

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ногодрыгом делать i2c это моветон.

Не надо говорить ерунды. Находиться в плену предрассудков - вот это точно моветон.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ногодрыгом делать i2c это моветон.

Ну почему же, вполне себе вариант в определенных обстоятельствах. В данном же случае - интерфейс работающий, не без нюансов, но "...всю Одессу удовлетворяет..."©

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...