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

I2C STM32F103. Фигнякакаято с инкрементом в прерывании

Пт янв 19, 2018 12:57:48

Доброго времени суток! Написал простейшую конструкцию для проверки работы хардварного I2C. Программка просто циклически посылает массив с циферками на анализатор. Фигня в том, что массив она посылает почему-то не с нулевого элемента, а с первого. Можно решить задачу через костыль, но это грубо. Что я упускаю? Код простейший, логи прикрепил:

Код:
#include "stm32f10x.h"

#define OLED_ADDR   0x78

uint8_t    i2c2_data[512]={1,2,3,4};
int16_t    i2c2_cnt;

void I2C2_INIT(){
   RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;

   GPIOB->CRH |= GPIO_CRH_CNF10 | GPIO_CRH_MODE10 | GPIO_CRH_CNF11 | GPIO_CRH_MODE11; //PB10, PB11 - OD, AF

   I2C2->CR1    |=  I2C_CR1_SWRST;
   I2C2->CR1    &= ~I2C_CR1_SWRST;
   I2C2->CR2   = 36 | I2C_CR2_ITEVTEN;
   I2C2->CCR   = I2C_CCR_FS | 30;
   I2C2->TRISE = 25;
   I2C2->CR1    |= I2C_CR1_PE;

   NVIC_EnableIRQ(I2C2_EV_IRQn);
}

void I2C_Write_massive(){

   I2C2->CR1 |= I2C_CR1_START;
}

int main(void){
   I2C2_INIT();

    while(1)
    {
       I2C_Write_massive(3);
       for(uint32_t i=0; i<360000; i++);
    }
}

void I2C2_EV_IRQHandler(){
   volatile uint32_t sr1 = I2C2->SR1, sr2 = I2C2->SR2;

   if(sr1 & I2C_SR1_SB ){
      I2C2->DR = OLED_ADDR;
   }
//---------- передача данных-------------------------------
   if((sr1 & I2C_SR1_TXE)){

      if(i2c2_cnt < 4){
         I2C2->DR = i2c2_data[i2c2_cnt++];
      }

      else{
         i2c2_cnt = 0;
         I2C2->CR1 |= I2C_CR1_STOP;
      }
   }
//----------
}
Вложения
I2C_Глюк.png
(70.86 KiB) Скачиваний: 60

Re: I2C STM32F103. Фигнякакаято с инкрементом в прерывании

Пт янв 19, 2018 13:09:32

переменные, используемые в прерывании, сделайте как volatile:
volatile int16_t i2c2_cnt;

Re: I2C STM32F103. Фигнякакаято с инкрементом в прерывании

Пт янв 19, 2018 13:26:03

Никак не повлияло. Попробовал сделать
Код:
i2c2_data[512]={0x78,1,2,3,4};
то есть, в нулевой элемент массива вкатил адрес устройства, и в обработчике сделал так, чтобы адрес читался из нулевого элемента массива
Код:
 if(sr1 & I2C_SR1_SB ){
      I2C2->DR = i2c2_data[0];
   }


Вот эта ерундовина отправляет то, что я хочу увидеть, но я не хочу записывать адрес в массив.

Добавлено after 8 minutes 56 seconds:
Проблему решил. Если кому пригодится, то в тело условия проверки флага старта добавил обнуление переменной i2c2_cnt = 0;
Код:
 if(sr1 & I2C_SR1_SB ){
      i2c2_cnt = 0;
      I2C2->DR = OLED_ADDR;
   }
      
Ответить