Jump to content
vis-vetal

F103C8 Передаёт 2 Байта По I2C

Recommended Posts

Всем привет. Столкнулся с проблемой, может кто уже сталкивался с подобным, или может хоть подскажите в какую сторону смотреть. Дело вот в чём: простая тестовая программа, передранная целиком и полностью из интернета(упростил в процессе поиска глюка, потом по функциям всё разложу) передаёт число 0х44 в устройство с адресом 0х12 по I2C.

Настроил тактирование контроллера, порты и сам интерфейс. Бросаю стартовый бит, нормально. Бросаю адрес, отлично. Отсылаю байт данных, а на выходе идёт 18 бит, то бишь 2 байта. В чём моя ошибка? Контроллер stm32f103C8T6. Среда - coocox.

Да там ещё была загвоздка, вместо проверки на окончание передачи адреса и самого байта пришлось ставить задержки. Я знаю что это колхоз, но не смог найти какой флаг проверять. Если кто подскажет буду очень рад.

Привожу код и скрин с анализатора.


#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_rcc.h"

//********************************************************************************
unsigned char InitClk()
{
unsigned long int TimeOut = 10000;
//Запустить HSE
RCC->CR |= RCC_CR_HSEON; //Включить генератор HSE
while((RCC->CR & RCC_CR_HSERDY)==0) //Ожидание готовности HSE
if(TimeOut) TimeOut--;
if(TimeOut==0) return 1; //Ошибка!!! Генератор HSE не запустился
RCC->CR |= RCC_CR_CSSON; //Разрешить работу системы защиты сбоя HSE
//Подключить систему к HSE
RCC->CFGR &= ~RCC_CFGR_SW; //Очистка битов выбора источника тактового сигнала
RCC->CFGR |= RCC_CFGR_SW_HSE; //Выбрать источником тактового сигнала HSE
//Настроить делитель для AHB
RCC->CFGR &= ~RCC_CFGR_HPRE; //Очистка битов предделителя "AHB Prescaler"
RCC->CFGR |= RCC_CFGR_HPRE_DIV2; //Установить "AHB Prescaler" равным 2
return 0; //Все ok, работаем от HSE
}
//********************************************************************************
//Function: обработчик прерывания при сбое генератора HSE //
//********************************************************************************
void NMI_Handler(void)
{
//Сбросить флаг системы контроля сбоя HSE
if (RCC->CIR & RCC_CIR_CSSF) RCC->CIR |= RCC_CIR_CSSC;
//Если контроллер здесь, значит HSE не работает
//Что-то можно предпринять: перезапустить генератор, дать сигнал аврии и т.п.
}
//********************************************************************************
GPIO_InitTypeDef gpio;
I2C_InitTypeDef i2c;
/*******************************************************************/
void init_I2C1(void)
{//Конфигурация I2C и портов под него
GPIO_PinRemapConfig(GPIO_Remap_I2C1, DISABLE);
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
I2C_DeInit (I2C1);
GPIO_DeInit(GPIOB);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 50000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
int main(void)
{
InitClk();
init_I2C1();
uint8_t transmissionDirection = I2C_Direction_Transmitter;
uint8_t slaveAddress = 0x12;
// Генерируем старт - тут все понятно )
I2C_GenerateSTART(I2C1, ENABLE);
// Ждем пока взлетит нужный флаг
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, slaveAddress, transmissionDirection);
uint8_t i;
for(i=0;i<0x50;i++);//Задержка на время адреса
uint8_t data = 0x44;
I2C_SendData(I2C1, data);
for(i=0;i<0x70;i++);//Задержка на время данных
I2C_GenerateSTOP(I2C1, ENABLE);
while(1){ }
}

post-48585-0-94993200-1405013710_thumb.jpg

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • By n_angelo
      Привет. Хочу узнать ваше мнение. Я новичок в embedded. Можно сказать, что пришел с веба. Малость Python, JS, C. Меня, конечно, предупреждали начать с AVR, но я уверенный в себе решил сразу залезть на STM32. Вынашивая идею для проекта, параллельно курив Reference Manual и Data Sheet по STM32, я понял что его будет слишком жирно для проекта. Я перескочил на STM8L. И тут меня начал огорчать мир embedded. При переходе между stm8 и stm32 нужно менять IDE (TrueStudio на STVD). Во избежание таких курьёзов я пересаживаюсь на IAR. В процессе подключения родной библиотеки от ST, понимаю что библиотека от IAR для того же самого STM8L152C6T6 дико отличается (макросы, структуры). Привет веб-разработка. Как такое могло произойти, что под один и тот же контроллер ST даёт одну библиотеку, а IAR другую. И нигде в уроках тебя не предупредят об этом. Ну, ребят, у меня всего одна жизнь. Вы уже договоритесь там между собой? Придите к единому стандарту. Или они так решили новичков завендерлочить? Моё мнение (не претендует на правильное): пробираясь сквозь тернии популярной архитектуры ARM, инфраструктуры, инструментария, забываешь про бизнес-логику устройств. А еще просто пропасть между "я ничего не понимаю" и "господи, я зажег светодиод". Речь не о копипастерах с уроков, а действительно понимая что ты делаешь, в каком регистре, что меняешь. Это путь в 2000 (а то и больше) страниц на английском перечитанных по несколько раз, чтобы отоложилось. И в конце тебя ждут разные версии одной и той же библиотки в разных IDE. И сидишь вдупляешь... ну почему... я же в правильный регистр кладу правильную маску... ох, наболело. Такое ощущение что не для людей это всё делали, не для людей.
      Ваше мнение?
    • By Sofia Vin
      Предлагаем проектную работу в Москве:
      Микроконтроллер STM32F103.
        
      Есть встроенный код с использованием функций библиотеки FreeRTOS, код имеет описанный протокол для связи с внешним миром.
        
      Необходимо проводить доработку кода под задачи программиста верхнего уровня и его тестирование в составе оборудования. 
      Работа в лаборатории (м.Университет) и удаленно. 
      Оплата по договоренности.
      Если Вы обладаете опытом схемотехнического проектирования и программирования микроконтроллеров, и Вас заинтересовала данная возможность, ждем Ваши отклики по контактным данным:
      8 (925) 023-60-02   Алексей
      E-mail: nassa@marathon.ru
       
    • By KVAnton
      Всем привет, начал недавно STM32 осваивать (до этого были pic12-18/arduino/raspberry) и столкнулся с интересной проблемой:
      Настроил GPIO как Input Pull-Up но при считывании получаю 0.
      Условия:
      Несколько других также настроенных портов (Input Pull-Up) при этом посажены на землю (на один порт Output Open-Drain), а непосредственно перед считыванием переключаю другой порт Output Open-Drain Pull-Up с 1 на 0.
      При этом, если поставить задержку (пробовал 1мс) после переключения OutPut и считыванием Input получаю - 1, как и должно быть. Порты по схеме ни как не связанны - пробовал вообще отключать input порт от схемы (матрица кнопок) ситуация не меняется.
      Работаю с китайской платой на stm32f103c8t6 (ардуино подобная) и библиотекой LL. Скорость порта пробовал разную - результат один.
      Сможет кто-то объяснить или хотя бы намекнуть (куда копать, что почитать) почему такой эффект возможен?
      Во всяких даташитах/аппликейшн ноте вроде ни чего интересного, зацепила только аббревиатура  SSO ( simultaneous switching output) в разделе Adapt GPIO speed (в AN на GPIO) - но понять глубину этой фразы и контекста с ходу не получилось (возможно из-за непонимания каких-то базовых моментов)
      Хотя и проблема в принципе решена (задержка допустима) - но хотелось бы разобраться в причинах.
      Буду благодарен любым вариантам, может что-то натолкнет на правильные мысли.
    • By katet
      Добрый день. Может быть,кто-нибудь уже сталкивался с таким. 
      Занимаюсь доработкой чужого проекта в среде STM32CubeMX, первый раз работаю с библиотекой HAL.
      В этом проекте осуществлялся прием байт по USART1 из ComMon. Проект был открыт в STM32CubeMX, где мной дополнительно были активированы новые модули - RTC, SD, USART2. Настройки USART1 не менялись. 
      Часы реального времени RTC: питание от батарейки, тактирование – от LSE. 
      При приеме байт по USART1 в новом проекте (активны  USART1, RTC, SD, USART2) было выявлено, что после приема 2 байт по USART1 перестает инкрементироваться значение переменной uwTick, отвечающей за прерывания Systick, в результате чего дальнейшая отладка невозможна. Не удается выяснить, в каком месте и почему перестает увеличиваться значение uwTick. При работе со старым проектом (где активен только USART1) uwTick инкрементируется после приема 2 байт.
      Смены приоритета прерываний не происходит, в  функцию HAL_Delay() отладчик не попадает. При вызове функции HAL_ResumeTick(), возобновляющей прерывания Systick, ничего не меняется, значение uwTick остается неизменным.
      Остановка прерываний была обнаружена при попадании в функцию:
      static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
      {
        /* Wait until flag is set */
        while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) 
        {
          /* Check for the Timeout */
          if(Timeout != HAL_MAX_DELAY)
          {            
            if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout))
            {
              /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
              CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE));
              CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
              
              huart->gState  = HAL_UART_STATE_READY;
              huart->RxState = HAL_UART_STATE_READY;
              
              /* Process Unlocked */
              __HAL_UNLOCK(huart);
              
              return HAL_TIMEOUT;
            }
          }
        }
        
        return HAL_OK;
      }
      В новом проекте текущее значение uwTick, возвращаемое функцией HAL_GetTick(), всегда равно значению Tickstart. В старом проекте сначала также, но затем uwTick начинает увеличиваться. Выяснить, в каком именно месте кода значение uwTick должно начать увеличиваться, не удается.
      Может быть, у кого-нибудь есть хоть какие-то идеи, с чем может быть связана остановка увеличения значений uwTick, помогите пожалуйста)
      Распиновка и конфигурация обоих проектов: верхняя часть рисунков - первоначальный, работающий вариант,  нижняя - сбой прерываний Systick.


×
×
  • Create New...