Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

STM32F030F4p6 i2c

Вс июл 11, 2021 18:56:02

здравствуйте .есть необходимость связать данный контроллер но шине I2C .написал код -все по мануалу (пока это отправка ) d keil .Прошли контроллер но на линии тишина... - бьюсь уже несколько дней но пока никак .Заранее спасибо за помощь!!

#define adress 0x7e

void i2c_init (void)
{

SET_BIT(RCC->AHBENR,RCC_AHBENR_GPIOAEN);


GPIOA->MODER |=GPIO_MODER_MODER9_1;
GPIOA->OSPEEDR|=GPIO_OSPEEDER_OSPEEDR9; //альтернативная функция AF4 для PA9
GPIOA->AFR[1]|=(4<<4);

GPIOA->MODER|=GPIO_MODER_MODER10_1;
GPIOA->OSPEEDR|=GPIO_OSPEEDER_OSPEEDR10; // //альтернативная функция AF4 для PA10
GPIOA->AFR[1]|=(4<<8);

RCC->APB1ENR |=RCC_APB1ENR_I2C1EN; // включаем тактирование
RCC->CFGR3|=RCC_CFGR3_I2C1SW; //источник тактирования
I2C1->TIMINGR=0X10420F13; // настройка таймингов при частоте 8 MHz
I2C1->CR1|=I2C_CR1_PE; // включаем модуль

}


void write_i2c (unsigned char adr,unsigned char data) //функция передачи
{
I2C1->CR2=I2C_CR2_AUTOEND|(2<<16)|I2C_CR2_START|(adress<<1); // передаем адрес ведомого , автостоп , условие старта.
while ((I2C1->ISR&I2C_ISR_TXE)!= I2C_ISR_TXE); //ждем передачи адреса
I2C1->TXDR=adr; //посылаем адрес ячейки в который хотим писать данные
while ((I2C1->ISR&I2C_ISR_TXIS)!= I2C_ISR_TXIS); //ждем окончания посылки
I2C1->TXDR=data; //отправляем данные
while ((I2C1->ISR&I2C_ISR_BUSY)==I2C_ISR_BUSY); //ждем освобождения шины

}

Re: STM32F030F4p6 i2c

Вс июл 11, 2021 19:05:52

Странный у Вас мануал.
В RM0360 Reference manual STM32F030x4/x6/x8/xC and STM32F070x6/xB advanced ARM®-based 32-bit MCUs
написано первым действием в инициализации: Clear PE bit in I2C_CR1

Возможно, Вы и дальше всё "упростили"?

Re: STM32F030F4p6 i2c

Пн июл 12, 2021 02:52:36

делал я и с отключенным модулем вначале и без этот -результата нет . Вот и спрашиваю что в моем коде не так .

Re: STM32F030F4p6 i2c

Пн июл 12, 2021 08:22:44

Не блокирующая реализация для STM32F030F4p6 i2c
Спойлер
Код:
#define I2C_BUS I2C1

// Вспомогательные переменные
typedef enum _I2C_Direction {I2C_Transmitter=0, I2C_Receiver=1} I2C_Direction;

void init_I2C1(void)
{
   RCC_I2CCLKConfig(RCC_I2C1CLK_HSI);   // I2C Clock Mux - HSI

   // Включаем тактирование нужных модулей
   RCC->AHBENR |= RCC_AHBENR_GPIOAEN;

   // Включаю тактирование I2C
   RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;      
   // Настройка ног PA9, PA10
   GPIOA->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;         // Режим альтернативной функции
   GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10;            // Открытый коллектор
   GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10;   // Максимальная скорость                  GPIO_OSPEEDER_OSPEEDR9
   // Выбор альтернативной функции
   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_4);   // I2C1_SCL
   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_4);   // I2C1_SDA

   I2C_BUS->CR1 &= ~I2C_CR1_PE;         // Отключаю I2C
   while (I2C_BUS->CR1 & I2C_CR1_PE) {};   // Жду пока отключится

   // Настраиваю тайминги
   I2C_BUS->TIMINGR = (uint32_t)0x00905E82;   // 48MHz 0x10400CDB-100kHz 0x00905E82-200kHz

   I2C_BUS->CR1 |= I2C_CR1_PE;               // Включаю I2C
   while ((I2C_BUS->CR1 & I2C_CR1_PE)==0) {};   // Жду пока включится
}

void I2C_Write_Transaction (uint8_t Adress, uint8_t Data)
{
   // Старт
   I2C_Start_Direction_Adress_Size (I2C_Transmitter, Adress, 1);

   // Сейчас либо I2C запросит первый байт для отправки,
   // Либо взлетит NACK-флаг, говорящий о том, что микросхема не отвечает.
   // Если взлетит NACK-флаг, отправку прекращаем.
   while ((((I2C_BUS->ISR & I2C_ISR_TXIS)==0) && ((I2C_BUS->ISR & I2C_ISR_NACKF)==0)) && (I2C_BUS->ISR & I2C_ISR_BUSY)) {};
   if (I2C_BUS->ISR & I2C_ISR_TXIS) I2C_BUS->TXDR=Data;   // Отправляю данные

   I2C_Stop();
}

void I2C_Start_Direction_Adress_Size (I2C_Direction Direction, uint8_t Adress, uint8_t Size)
{
   //I2C_BUS->CR2 &= ~I2C_CR2_AUTOEND;            // Выдавать стоп вручную
   //I2C_BUS->CR2 &= ~I2C_CR2_RELOAD;            // Не использовать режим перезагрузки
   if (Direction) I2C_BUS->CR2 |= I2C_CR2_RD_WRN;   // Режим приёма
   else I2C_BUS->CR2 &= ~I2C_CR2_RD_WRN;         // Режим передачи
   I2C_BUS->CR2 &= ~I2C_CR2_NBYTES;            // Очистить размер данных
   I2C_BUS->CR2 |= Size<<I2C_OFFSET_CR2_NBYTES;   // Установить размер данных
   I2C_BUS->CR2 &= ~I2C_CR2_SADD;   // Очистить адрес ведомого устройства
   I2C_BUS->CR2 |= (Adress << 1);         // Установить адрес ведомого устройства
   I2C_BUS->CR2 |= I2C_CR2_START;               // Выдать старт на шину
   while ((I2C_BUS->ISR & I2C_ISR_BUSY)==0) {};   // Ожидать выдачу старта
}

void I2C_Stop (void)
{
   I2C_BUS->CR2 |= I2C_CR2_STOP;            // Выдать стоп на шину
   while (I2C_BUS->ISR & I2C_ISR_BUSY) {};      // Ожидать выдачу стопа
   // Очищаю флаги - необходимо для дальнейшей работы шины
   I2C_BUS->ICR |= I2C_ICR_STOPCF;      // STOP флаг
   I2C_BUS->ICR |= I2C_ICR_NACKCF;      // NACK флаг
   // Если есть ошибки на шине - очищаю флаги
   if (I2C_BUS->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR))
   {
      I2C_BUS->ICR |= I2C_ICR_ARLOCF;
      I2C_BUS->ICR |= I2C_ICR_BERRCF;
   }
}

Re: STM32F030F4p6 i2c

Пн июл 12, 2021 11:37:37

Dimon456, здесь "не" лишнее. Неблокирующая — это когда нет блокировки. Т.е. прием-передача через DMA или хотя бы на прерываниях.
А блокирующую и я могу предложить.

Re: STM32F030F4p6 i2c

Пн июл 12, 2021 12:28:18

Eddy_Em вот сканер
Спойлер
Код:
uint8_t adress_as[127];
void skaner(void)
{
   for(uint8_t address = 8; address < 127; address++ ) {

      I2C_Start_Direction_Adress_Size (I2C_Transmitter, address, 1);

      // Сейчас либо I2C запросит первый байт для отправки,
       // Либо взлетит NACK-флаг, говорящий о том, что микросхема не отвечает.
       // Если взлетит NACK-флаг, отправку прекращаем.
       while ((((I2C_BUS->ISR & I2C_ISR_TXIS)==0) && ((I2C_BUS->ISR & I2C_ISR_NACKF)==0)) && (I2C_BUS->ISR & I2C_ISR_BUSY)) {};
       if (I2C_BUS->ISR & I2C_ISR_TXIS) {
          adress_as[address]=address;  //
          I2C_BUS->TXDR=0x00;   // Отправляю хоть что-то, иначе виснет
       }

      I2C_Stop();
   }
}
Eddy_Em писал(а):Т.е. прием-передача через DMA
У меня и с DMA есть, правда только передача на mcp4725, и режим FAST_MODE 1МГц.

Re: STM32F030F4p6 i2c

Пн июл 12, 2021 19:45:29

У меня была подобная проблема,оказалось что была включена собака и программа просто не успевала доходить до участка исходника где отправка по I2C,поставил так и все завелось http://forumupload.ru/uploads/0000/25/b8/385/392026.png
Ответить