Jump to content

    

Donker

Участник
  • Content Count

    90
  • Joined

  • Last visited

Posts posted by Donker


  1. Ладно, допустим с выводом за раз, и без прерываний, массива более 255 байт на STM32F0 через DMA я пролетаю, но как
    отправить хотя бы 255 байт?

     Вот так:

     

     
    
    //--------------------------------------------------------------------------------------------
    	uint8_t screen_buff[512];
    #define    OLED_addr_127 0b00111100        //7-битный адрес OLED         0b01111000 = 0x78
     
    //--------------------------------------------------------------------------------------------
    	void I2C_init(void)
    {
    RCC->AHBENR |= RCC_AHBENR_DMA1EN; /* Enable the peripheral clock DMA1 */
    	/* DMA1 Channel4 I2C1_TX config */ /*      Memory to peripheral */ /*      8-bit transfer */
    DMA1_Channel2->CPAR = (uint32_t)&(I2C1->TXDR);    /* (1)  Peripheral address */
    DMA1_Channel2->CMAR = (uint32_t)screen_buff;      /* (2)  Memory address */
    DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_DIR; /* (3)  Memory increment */
        
    //------------------------------------------------------------------------------------    
        
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;  /* Enable the peripheral clock I2C1 */
    RCC->CFGR3 |= RCC_CFGR3_I2C1SW;    
    	/* Configure I2C1, master */
    /* (1) Timing register value is computed with the AN4235 xls file,
     fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */
    /* (2) Periph enable */
    /* (3) Slave address = 0x5A, write transfer, 1 byte to transmit, autoend */
    I2C1->TIMINGR = (uint32_t)0x00B01A4B;                         /* (1) */
    I2C1->CR1 = I2C_CR1_PE;                                       /* (2) */
    I2C1->CR2 = I2C_CR2_AUTOEND | (255<<16) | (OLED_addr_127<<1); /* (3) */
    }
    	//--------------------------------------------------------------------------------------------
    	void OLED_SendScreen(void)
    {    
    if((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
      {
      // I2C2->TXDR = I2C_BYTE_TO_SEND; /* Byte to send */
        //I2C2->CR2 |= I2C_CR2_START; /* Go */
        /* start transmission with DMA */
        DMA1_Channel2->CCR &=~ DMA_CCR_EN;
        DMA1_Channel2->CNDTR = 255; /* Data size */
        DMA1_Channel2->CCR |= DMA_CCR_EN;
        
        I2C1->CR2 |= I2C_CR2_START; /* Go */
      }        
    }    
    //--------------------------------------------------------------------------------------------
    

     

     

     

     

     

    не отправляется, в ЛА видно что есть старт, и правильно с нормальной скоростью отправляется адрес устройства,
    и всё, больше никаких байт не идёт и стопа тоже нет.
     Что не так?

    Код практически целиком взят из снипетов (см. 1 пост),  только изменён I2C2 на  I2C1 и канал DMA c 4 на 2
     (в снипетах код для STM32F072RBT)

  2. Возникли вопросы по регистру I2C1->CR2 в STM32F030F4:

    Cудя по дащиту (RM стр. 518) там есть секция "NBYTES" которая имеет размерность 8 бит и куда
    записывается количество байт для передачи (максимум 255), т.е. по максимуму это выглядит так:

    I2C1->CR2 =  I2C_CR2_AUTOEND | (256<<16) | (OLED_addr_127<<1); /* (3) */
    

    я правильно понимаю, что этота секция не даст отправить вподряд более 255 байт между "старт-адрес-..байты...-стоп"?

    Этот же регистр не даст передать по DMA более 255 байт вподряд, хотя у DMA есть регистр DMA1_Channel2->CNDTR
    куда можно записать уже 16 бит ?

  3. Нашёл ошибку - перепутал AF4 на котором сидит I2C в STM32F030F4  cо смещением номера вывода, правильно так:

    GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10;                                                                    /* (1) Open drain for I2C signals */
    GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | (4 << ((9 - 8) * 4)) | (4 << ((10 - 8) * 4));    /* (2) AF4 for I2C signals */
    GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); /* (3) Select AF mode (0b10) on PA9 and PA10 */

    Поток пошёл, сейчас разбираюсь с порядком следования байт.

  4. Пока решил заняться STM32F030F4, для STM32F030F4 у меня работает только ногодрыг, не получается запустить аппаратный I2C, вот часть кода:

     

    Спойлер

     

    
    //--------------------------------------------------------------------------------------------
    #define    OLED_addr_127 0b00111100        //7-битный адрес OLED         0b01111000 = 0x78
    //--------------------------------------------------------------------------------------------
    RCC->AHBENR |= RCC_AHBENR_GPIOAEN; //включаем тактирование
    
    GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10;   /* (1) Open drain for I2C signals */
    GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | (0x01 << (1 * 4)) | (0x01 << (2 * 4));    /* (2) AF1 for I2C signals */
    GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1);   /* (3) Select AF mode (10) on PA9 and PA10 */
    //--------------------------------------------------------------------------------------------
    void I2C_init(void)
    {
     
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;  /* Enable the peripheral clock I2C2 */
    RCC->CFGR3 |= RCC_CFGR3_I2C1SW;    
    
    /* Configure I2C2, master */
    /* (1) Timing register value is computed with the AN4235 xls file,
     fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */
    /* (2) Periph enable */
    /* (3) Slave address = 0x5A, write transfer, 1 byte to transmit, autoend */
    I2C1->TIMINGR = (uint32_t)0x00B01A4B; /* (1) */
    I2C1->CR1 = I2C_CR1_PE; /* (2) */
    I2C1->CR2 =  I2C_CR2_AUTOEND | (1<<16) | (OLED_addr_127<<1); /* (3) */
    
    }
    //--------------------------------------------------------------------------------------------
    void I2C_StartCondition(void) //СТАРТ
    {
    I2C1->CR2 |= I2C_CR2_START; /* Go */
    }
    //--------------------------------------------------------------------------------------------
    void I2C_StopCondition(void) //СТОП
    {
    I2C1->CR2 |= I2C_CR2_STOP;
    }
    //--------------------------------------------------------------------------------------------
    void I2C_SendByte(unsigned char data) //ПЕРЕДАЧА БАЙТА и АСК
    {
    if((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
      {    
      I2C1->TXDR = data; /* Byte to send */
        I2C1->CR2 |= I2C_CR2_START; /* Go */    
        }
    //while (0 == (I2C1->ISR & I2C_ISR_TXE)){}    
    }
    //--------------------------------------------------------------------------------------------

     

    может кто нибудь заметит ошибку, пока что в ЛА невидно вообще никакой активности на линиях I2C
    они сидят в высоком уровне даже в момент ресета.

  5. Что-то не работает моя переделка снипета от F0

    Вот часть кода:

    Спойлер

     

    
    //--------------------------------------------------------------------------------------------
    
    #define        NAME        0b01111000        //АДРЕС УСТРОЙСТВА НА ШИНЕ        0b01111000 = 0x78
    #define        DATS        0b01000000        //ПЕРЕДАЧА НЕСКОЛЬКИХ БАЙТ ДАННЫХ 0b01000000 = 0x40
    #define        DAT            0b11000000        //ПЕРЕДАЧА ОДНОГО БАЙТа ДАННЫХ    0b11000000 = 0xC0
    #define        COM            0b10000000        //ПЕРЕДАЧА ОДНОГО БАЙТа КОМАНДЫ   0b10000000 = 0x80
    
    uint8_t screen_buff[513]; //буффер экрана 512 байт ((128x32)/8) + самый первый байт для команды DATS
    
    //--------------------------------------------------------------------------------------------
    
    void DMA_init(void)
    {
    ////////////////////////////////////////////////////////////////////////    
    RCC->AHBENR |= RCC_AHBENR_DMA1EN; /* Enable the peripheral clock DMA1 */
    
    /* DMA1 Channel4 I2C1_TX config */
    /*      Memory to peripheral */                                        
    /*      8-bit transfer */
    DMA1_Channel4->CPAR = (uint32_t)&(I2C1->DR);         //* (1)  Peripheral address */ DMA1_Channel4->CPAR = (uint32_t)&(I2C1->TXDR);
    DMA1_Channel4->CMAR = (uint32_t)screen_buff;         //* (2)  Memory address */
    DMA1_Channel4->CCR |= DMA_CCR4_MINC | DMA_CCR4_DIR;  //* (3)  Memory increment */ DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR;
    ////////////////////////////////////////////////////////////////////////    
    }
    
    void I2C_init(void)
    {
    //////////////////////////////////////////////////////////////////////////////////////    
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //включаем тактирование I2C1
    
    I2C1->CR2 &= ~I2C_CR2_FREQ;
    I2C1->CR2 |= 36; //частота APB1 в мгц //36
    
    I2C1->CCR &= ~I2C_CCR_CCR;
    I2C1->CCR |= 30; //частота SCL//34//
    I2C1->CCR |= I2C_CCR_FS; //выбор режима SM Standart mode – 100КГц  или FM Fast mode - 400КГц
    
    I2C1->TRISE = 12; //максимальное время нарастания импульса //12
    
    I2C1->CR1 |= I2C_CR1_PE; //включаем I2C1
    //---------------------------------настройки для DMA--------------------------------------------------
    I2C1->CR1 = I2C_CR1_PE | I2C_CR2_DMAEN;  /* (2) Periph enable */
    I2C1->CR2 =  (512 << 16) | (NAME<<0); /* (3) Slave address = 0x5A, write transfer, 2 bytes to transmit, autoend */ //I2C_CR2_AUTOEND - это где брать?
    //////////////////////////////////////////////////////////////////////////////////////
    }
    
    void OLED_SendScreen(void)
    {
    //////////////////////////////////////////////////////////////////////////////////////
    //---------------------Посылка буфера экрана через без DMA(работает) -----------------    
    //I2C_StartCondition();  
    //I2C_SendAddr();  //I2C_SendByte(NAME);        //посыл адреса+0
    //for(unsigned int i=0; i<513; i++)
    //  {
    //  I2C_SendByte(screen_buff[i]);
    //  }
    //I2C_StopCondition();     
    //---------------------Посылка буфера экрана через DMA(не работает) ------------------    
        
    //if((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE))  /* Check Tx empty */
     
        /* start transmission with DMA */
        DMA1_Channel4->CCR &=~ DMA_CCR4_EN;
        DMA1_Channel4->CNDTR = 513;/* Data size */
        DMA1_Channel4->CCR |= DMA_CCR4_EN;
    
        I2C1->CR1 |= I2C_CR1_START; /* Go */     
    //////////////////////////////////////////////////////////////////////////////////////        
    }
    
    void OLED_init(void)  //ИНИЦИАЛИЗАЦИЯ ДИСПЛЕЯ
    {
    //////////////////////////////////////////////////////////////////////////////////////
    I2C_init();    
    DMA_init();        
    I2C_StartCondition();
    I2C_SendAddr();  
    for(unsigned char k=0; k<31; k++)
        {
        I2C_SendByte(COM);
        I2C_SendByte(ini_mass[k]);
        }
    I2C_StopCondition();    
    screen_buff[0] =     DATS;
    //////////////////////////////////////////////////////////////////////////////////////    
    }
    //--------------------------------------------------------------------------------------------

     


     

    Если раскомментировать в функции OLED_SendScreen пересылку без DMA - тогда работает, если выполнить
    OLED_SendScreen в том виде как сейчас, в ЛА видно что происходит "условие старт", после чего линии лежат
    в нуле и ничего не передаётся.

    Снипет смотрел этот:

     

    Спойлер

     

    
    **
      ******************************************************************************
      * @file    03_CommunicationUsingDMA/main.c
      * @author  MCD Application Team
      * @version V1.2.0
      * @date    19-June-2015
      * @brief   This code example shows how to configure the GPIOs and I2C
      *          in order to receive with slave and transmit with master.
      *
     ===============================================================================
                        #####       MCU Resources     #####
     ===============================================================================
       - RCC
       - GPIO PB6(I2C1_SCL),PB7(I2C1_SDA),PB10(I2C2_SCL),PB11(I2C2_SDA),PA0,PC8,PC9
       - I2C1 (slave), I2C2 (master)
       - EXTI
       
     ===============================================================================
                        ##### How to use this example #####
     ===============================================================================
       - this file must be inserted in a project containing  the following files :
          o system_stm32f0xx.c, startup_stm32f072xb.s
          o stm32f0xx.h to get the register definitions
          o CMSIS files
    
    
     ===============================================================================
                        ##### How to test this example #####
     ===============================================================================
       - Plug wires between PB6/PB10 and PB7/PB11, 4K7 PU are already on the board.
       - Launch the program
       - Press the user button to initiate a transmit request by master
         then slave receivess a byte
       - The green and orange LEDs toggles if everything goes well
    
      *    
      ******************************************************************************
      * @attention
      *
      * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
      *
      * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
      * You may not use this file except in compliance with the License.
      * You may obtain a copy of the License at:
      *
      *        http://www.st.com/software_license_agreement_liberty_v2
      *
      * Unless required by applicable law or agreed to in writing, software
      * distributed under the License is distributed on an "AS IS" BASIS,
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      * See the License for the specific language governing permissions and
      * limitations under the License.
      *
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "stm32f0xx.h"
    
    /** @addtogroup STM32F0_Snippets
      * @{
      */
    
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    #define I2C1_OWN_ADDRESS (0x5A)
    #define I2C_CMD_TOGGLE_ORANGE (0x81)
    #define I2C_CMD_TOGGLE_GREEN (0x82)
    #define SIZE_OF_DATA  (2)
    
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    uint8_t datatosend[SIZE_OF_DATA]={I2C_CMD_TOGGLE_ORANGE,I2C_CMD_TOGGLE_GREEN};
    uint8_t datatoreceive[SIZE_OF_DATA];
    
    /* Private function prototypes -----------------------------------------------*/
    void Configure_GPIO_LED(void);
    void Configure_GPIO_I2C1(void);
    void Configure_DMA_I2C1(void);
    void Configure_I2C1_Slave(void);
    void Configure_GPIO_I2C2(void);
    void Configure_DMA_I2C2(void);
    void Configure_I2C2_Master(void);
    void Configure_GPIO_Button(void);
    void Configure_EXTI(void);
    
    /* Private functions ---------------------------------------------------------*/
    
    /**
      * @brief  Main program.
      * @param  None
      * @retval None
      */
    int main(void)
    {
      /*!< At this stage the microcontroller clock setting is already configured,
           this is done through SystemInit() function which is called from startup
           file (startup_stm32f072xb.s) before to branch to application main.
           To reconfigure the default setting of SystemInit() function, refer to
           system_stm32f0xx.c file
         */
    
      Configure_GPIO_LED();
      Configure_GPIO_I2C1();
      Configure_DMA_I2C1();
      Configure_I2C1_Slave();
      Configure_GPIO_I2C2();
      Configure_DMA_I2C2();
      Configure_I2C2_Master();
      Configure_GPIO_Button();
      Configure_EXTI();
    
      /* Initiate I2C sequence in button IRQ handler */
        
      /* Infinite loop */
      while (1)
      {
    
      }
    }
    
    /**
      * @brief  This function :
                 - Enables GPIO clock
                 - Configures the Green LED pin on GPIO PC9
                 - Configures the orange LED pin on GPIO PC8
      * @param  None
      * @retval None
      */
    __INLINE void Configure_GPIO_LED(void)
    {
      /* Enable the peripheral clock of GPIOC */
      RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
        
      /* Select output mode (01) on PC8 and PC9 */
      GPIOC->MODER = (GPIOC->MODER & ~(GPIO_MODER_MODER8 | GPIO_MODER_MODER9)) \
                     | (GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0);
    }
    
    /**
      * @brief  This function :
                 - Enables GPIO clock
                 - Configures the I2C1 pins on GPIO PB6 PB7
      * @param  None
      * @retval None
      */
    __INLINE void Configure_GPIO_I2C1(void)
    {
      /* Enable the peripheral clock of GPIOB */
      RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
        
      /* (1) open drain for I2C signals */
      /* (2) AF1 for I2C signals */
      /* (3) Select AF mode (10) on PB6 and PB7 */
      GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7; /* (1) */
      GPIOB->AFR[0] = (GPIOB->AFR[0] & ~(GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)) \
                      | (1 << ( 6 * 4 )) | (1 << (7 * 4)); /* (2) */
      GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7)) \
                     | (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1); /* (3) */
    
    }
    
    /**
      * @brief  This function configures DMA for I2C1.
      * @param  None
      * @retval None
      */
    __INLINE void Configure_DMA_I2C1(void)
    {
      /* Enable the peripheral clock DMA1 */
      RCC->AHBENR |= RCC_AHBENR_DMA1EN;
     
       /* DMA1 Channel2 I2C1_RX config */
      /* (4)  Peripheral address */
      /* (5)  Memory address */
      /* (6)  Data size */
      /* (7)  Memory increment */
      /*      Peripheral to memory*/
      /*      8-bit transfer */
      /*      Transfer complete IT */
      DMA1_Channel3->CPAR = (uint32_t)&(I2C1->RXDR); /* (4) */
      DMA1_Channel3->CMAR = (uint32_t)datatoreceive; /* (5) */
      DMA1_Channel3->CNDTR = SIZE_OF_DATA; /* (6) */
      DMA1_Channel3->CCR |= DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN; /* (7) */
     
      /* Configure IT */
      /* (8) Set priority for DMA1_Channel2_3_IRQn */
      /* (9) Enable DMA1_Channel2_3_IRQn */
      NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0); /* (8) */
      NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /* (9) */
    }
    
    /**
      * @brief  This function configures I2C1, slave.
      * @param  None
      * @retval None
      */
    __INLINE void Configure_I2C1_Slave(void)
    {
      /* Configure RCC for I2C1 */
      /* (1) Enable the peripheral clock I2C1 */
      /* (2) Use SysClk for I2C CLK */
      RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* (1) */
      RCC->CFGR3 |= RCC_CFGR3_I2C1SW; /* (2) */
     
      /* Configure I2C1, slave */
      /* (2) Timing register value is computed with the AN4235 xls file,
       fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */
      /* (3) Periph enable, receive DMA enable */
      /* (4) 7-bit address = 0x5A */
      /* (5) Enable own address 1 */
      I2C1->TIMINGR = (uint32_t)0x00B00000; /* (2) */
      I2C1->CR1 = I2C_CR1_PE | I2C_CR1_RXDMAEN | I2C_CR1_ADDRIE; /* (3) */
      I2C1->OAR1 |= (uint32_t)(I2C1_OWN_ADDRESS << 1); /* (4) */
      I2C1->OAR1 |= I2C_OAR1_OA1EN; /* (5) */
     
      /* Configure IT */
      /* (7) Set priority for I2C1_IRQn */
      /* (8) Enable I2C1_IRQn */
      NVIC_SetPriority(I2C1_IRQn, 0); /* (7) */
      NVIC_EnableIRQ(I2C1_IRQn); /* (8) */
    }
    
    /**
      * @brief  This function :
                 - Enables GPIO clock
                 - Configures the I2C2 pins on GPIO PB10 PB11
      * @param  None
      * @retval None
      */
    __INLINE void Configure_GPIO_I2C2(void)
    {
      /* Enable the peripheral clock of GPIOB */
      RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
        
      /* (1) Open drain for I2C signals */
      /* (2) AF1 for I2C signals */
      /* (3) Select AF mode (10) on PB10 and PB11 */
      GPIOB->OTYPER |= GPIO_OTYPER_OT_10 | GPIO_OTYPER_OT_11; /* (1) */
      GPIOB->AFR[1] = (GPIOB->AFR[1] &~ (GPIO_AFRH_AFRH2 | GPIO_AFRH_AFRH3)) \
                      | (1 << (2 * 4)) | (1 << (3 * 4)); /* (2) */
      GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER10 | GPIO_MODER_MODER11)) \
                     | (GPIO_MODER_MODER10_1 | GPIO_MODER_MODER11_1); /* (3) */
     
    }
    
    /**
      * @brief  This function configures DMA for I2C2.
      * @param  None
      * @retval None
      */
    __INLINE void Configure_DMA_I2C2(void)
    {
      /* Enable the peripheral clock DMA1 */
      RCC->AHBENR |= RCC_AHBENR_DMA1EN;
     
      /* DMA1 Channel4 I2C2_TX config */
      /* (1)  Peripheral address */
      /* (2)  Memory address */
      /* (3)  Memory increment */
      /*      Memory to peripheral */
      /*      8-bit transfer */
      DMA1_Channel4->CPAR = (uint32_t)&(I2C2->TXDR); /* (1) */
      DMA1_Channel4->CMAR = (uint32_t)datatosend; /* (2) */
      DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR; /* (3) */
    }
    
    /**
      * @brief  This function configures I2C2, master.
      * @param  None
      * @retval None
      */
    __INLINE void Configure_I2C2_Master(void)
    {
      /* Enable the peripheral clock I2C2 */
      RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
    
      /* Configure I2C2, master */
      /* (1) Timing register value is computed with the AN4235 xls file,
       fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */
      /* (2) Periph enable */
      /* (3) Slave address = 0x5A, write transfer, 2 bytes to transmit, autoend */
      I2C2->TIMINGR = (uint32_t)0x00B01A4B; /* (1) */
      I2C2->CR1 = I2C_CR1_PE | I2C_CR1_TXDMAEN; /* (2) */
      I2C2->CR2 =  I2C_CR2_AUTOEND | (SIZE_OF_DATA << 16) | (I2C1_OWN_ADDRESS<<1); /* (3) */
    }
    
    /**
      * @brief  This function :
                 - Enables GPIO clock
                 - Configures the Push Button GPIO PA0
      * @param  None
      * @retval None
      */
    __INLINE void Configure_GPIO_Button(void)
    {
      /* Enable the peripheral clock of GPIOA */
      RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
        
      /* Select mode */
      /* Select input mode (00) on PA0 */
      GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER0));
    }
    
    /**
      * @brief  This function configures EXTI.
      * @param  None
      * @retval None
      */
    __INLINE void Configure_EXTI(void)
    {
      /* Configure Syscfg, exti and nvic for pushbutton PA0 */
      /* (1) PA0 as source input */
      /* (2) unmask port 0 */
      /* (3) Rising edge */
      /* (4) Set priority */
      /* (5) Enable EXTI0_1_IRQn */
      SYSCFG->EXTICR[0] = (SYSCFG->EXTICR[0] & ~SYSCFG_EXTICR1_EXTI0) | SYSCFG_EXTICR1_EXTI0_PA; /* (1) */
      EXTI->IMR |= EXTI_IMR_MR0; /* (2) */
      EXTI->RTSR |= EXTI_RTSR_TR0; /* (3) */
      NVIC_SetPriority(EXTI0_1_IRQn, 0); /* (4) */
      NVIC_EnableIRQ(EXTI0_1_IRQn); /* (5) */
    }
    
    /******************************************************************************/
    /*            Cortex-M0 Processor Exceptions Handlers                         */
    /******************************************************************************/
    
    /**
      * @brief  This function handles NMI exception.
      * @param  None
      * @retval None
      */
    void NMI_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles Hard Fault exception.
      * @param  None
      * @retval None
      */
    void HardFault_Handler(void)
    {
      /* Go to infinite loop when Hard Fault exception occurs */
      while (1)
      {
      }
    }
    
    /**
      * @brief  This function handles SVCall exception.
      * @param  None
      * @retval None
      */
    void SVC_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles PendSVC exception.
      * @param  None
      * @retval None
      */
    void PendSV_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles SysTick Handler.
      * @param  None
      * @retval None
      */
    void SysTick_Handler(void)
    {
    }
    
    
    /**
      * @brief  This function handles EXTI 0 1 interrupt request.
      * @param  None
      * @retval None
      */
    void EXTI0_1_IRQHandler(void)
    {
      EXTI->PR |= 1;    
    
      /* start I2C master transmission sequence */
      if((I2C2->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
      {
       // I2C2->TXDR = I2C_BYTE_TO_SEND; /* Byte to send */
        //I2C2->CR2 |= I2C_CR2_START; /* Go */
        /* start transmission with DMA */
        DMA1_Channel4->CCR &=~ DMA_CCR_EN;
        DMA1_Channel4->CNDTR = SIZE_OF_DATA;/* Data size */
        DMA1_Channel4->CCR |= DMA_CCR_EN;
        
        I2C2->CR2 |= I2C_CR2_START; /* Go */
      }
    }
    
    /**
      * @brief  This function handles I2C1 interrupt request.
      * @param  None
      * @retval None
      */
    void I2C1_IRQHandler(void)
    {
      uint32_t I2C_InterruptStatus = I2C1->ISR; /* Get interrupt status */
     
      if((I2C_InterruptStatus & I2C_ISR_ADDR) == I2C_ISR_ADDR)
      {
        I2C1->ICR |= I2C_ICR_ADDRCF; /* Address match event */
      }
    }
    
    /**
      * @brief  This function handles DMA1 channel 2 and 3 interrupt request.
      * @param  None
      * @retval None
      */
    void DMA1_Channel2_3_IRQHandler(void)
    {
      if((DMA1->ISR & DMA_ISR_TCIF3) == DMA_ISR_TCIF3)
      {
        DMA1->IFCR |= DMA_IFCR_CTCIF3;/* Clear TC flag */
    
        if(datatoreceive[0] == I2C_CMD_TOGGLE_ORANGE)
        {
          datatoreceive[0]=0;
          GPIOC->ODR ^= GPIO_ODR_8; /* Toggle orange LED */
        }
        
        if(datatoreceive[1] == I2C_CMD_TOGGLE_GREEN)
        {
          datatoreceive[1]=0;
          GPIOC->ODR ^= GPIO_ODR_9; /* toggle green LED */
        }
        
        DMA1_Channel3->CCR &=~ DMA_CCR_EN;
        DMA1_Channel3->CNDTR = SIZE_OF_DATA;/* Data size */
        DMA1_Channel3->CCR |= DMA_CCR_EN;
      }
      else
      {
        NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);/* Disable DMA1_Channel2_3_IRQn */
      }
    }
    
    /**
      * @}
      */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

     

     

  6. Я просто не пойму почему в версии проекта с ногодрыгом я отправлял абсолютно все байты, включая адрес, на экран одной функцией:

     

    Спойлер

     

    
    void I2C_SendByte(unsigned char data) //ПЕРЕДАЧА БАЙТА и АСК
    {
    //////////////////////////////////////////////////////////////////////////////////////		
    for(unsigned char k=8; k>0; k--)
      {
    	if(data&(1<<(k-1)))
    	  {
    		SCL_LOW;
    		SDA_HI;
    		_delay_us(1); //подобрать
    		SCL_HI;
    		_delay_us(1); //подобрать
    		SCL_LOW;
    	  }
    	  else
    	    {
    		  SCL_LOW;
    			SDA_LOW;
    			_delay_us(1); //подобрать
    			SCL_HI;
    			_delay_us(1); //подобрать
    			SCL_LOW;
    	    }
    }
    _delay_us(1); //подобрать
    //--------------ACK-------------
    SDA_HI; 
    _delay_us(1); //подобрать
    SCL_HI;
    _delay_us(1); //подобрать
    //------------------------------
    if(!SDA_inp) {SCL_LOW;}
    _delay_us(3); //подобрать
    //////////////////////////////////////////////////////////////////////////////////////		 

     

    а в аппаратной версии, если попытаюсь вместо I2C_SendAddr использовать  I2C_SendByte, адрес отправляется, экран нормально реагирует,

    но  происходит бесконечное зависание на этапе ожидания бита подтверждения отправки байта:

    while (0 == (I2C1->SR1 & I2C_SR1_TXE)){}
  7. Как отправить массив (uint8_t) по I2C через DMA на STM32F105RBT6 или STM32F030F4 используя CMSIS?   
    Желательно сначала разобраться как это сделать на STM32F105RBT6 а потом перенести код на STM32F030F4.

    Сейчас я отправляю на STM32F105RBT6 без DMA буффер OLED экрана (SSD1306 128x32) таким образом:

    Спойлер

     

    
    //--------------------------------------------------------------------------------------------
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //включаем тактирование
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;  //6,7 I2C экрана
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //выход открытый коллектор
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);    
    GPIOB->BSRR = GPIO_BSRR_BS6; //высокий уровень
    GPIOB->BSRR = GPIO_BSRR_BS7; //высокий уровень
    //--------------------------------------------------------------------------------------------
    #define F_CPU 72000000UL
    
    #define        NAME        0b01111000        //АДРЕС УСТРОЙСТВА НА ШИНЕ        0b01111000 = 0x78
    #define        DATS        0b01000000        //ПЕРЕДАЧА НЕСКОЛЬКИХ БАЙТ ДАННЫХ 0b01000000 = 0x40
    #define        DAT            0b11000000        //ПЕРЕДАЧА ОДНОГО БАЙТа ДАННЫХ    0b11000000 = 0xC0
    
    uint8_t screen_buff[512]; //(128x32)/8
    //--------------------------------------------------------------------------------------------
    
    void I2C_init(void)
    {
    //////////////////////////////////////////////////////////////////////////////////////    
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //включаем тактирование I2C1
    
    I2C1->CR2 &= ~I2C_CR2_FREQ;
    I2C1->CR2 |= 36; //частота APB1 в мгц
    
    I2C1->CCR &= ~I2C_CCR_CCR;
    I2C1->CCR |= 30; //частота SCL
    I2C1->CCR |= I2C_CCR_FS; //выбор режима SM Standart mode – 100КГц  или FM Fast mode - 400КГц
    
    I2C1->TRISE = 12; //максимальное время нарастания импульса
    
    I2C1->CR1 |= I2C_CR1_PE; //включаем I2C1
    //////////////////////////////////////////////////////////////////////////////////////
    }
    void I2C_StartCondition(void) //СТАРТ
    {
    ///////////////////////////////////////////////
    I2C1->CR1 |= I2C_CR1_START;       
    while (!(I2C1->SR1 & I2C_SR1_SB)){}
    (void) I2C1->SR1;
    ///////////////////////////////////////////////            
    }
    void I2C_StopCondition(void) //СТОП
    {
    ////////////////////////////////////////    
    while (!(I2C1->SR1 & I2C_SR1_BTF)){}    
    I2C1->CR1 |= I2C_CR1_STOP;
    ///////////////////////////////////////
    }
    void I2C_SendByte(unsigned char data)
    {
    //////////////////////////////////////////////////////////////////////////////////////        
    I2C1->DR = data;
    while (0 == (I2C1->SR1 & I2C_SR1_TXE)){}
    //////////////////////////////////////////////////////////////////////////////////////        
    }
    void I2C_SendAddr(void)
    {
    //////////////////////////////////////////////////////////////////////////////////////        
    I2C1->DR = NAME;
    while (!(I2C1->SR1 & I2C_SR1_ADDR)){}
    (void) I2C1->SR1;
    (void) I2C1->SR2;
    //////////////////////////////////////////////////////////////////////////////////////        
    }
    void OLED_SendScreen(void)
    {
    //////////////////////////////////////////////////////////////////////////////////////    
    I2C_StartCondition();  
    I2C_SendAddr();      //посыл адреса+0
    I2C_SendByte(DATS);    
    for(unsigned int i=0; i<512; i++)
      {
      I2C_SendByte(screen_buff[i]);
      }
    I2C_StopCondition();
    //////////////////////////////////////////////////////////////////////////////////////        
    }    
    
    //--------------------------------------------------------------------------------------------

     

    как сюда прикрутить DMA?

    Можно как то обойтись без функции I2C_SendAddr используя только I2C_SendByte (добавив адрес  в начало массива) что бы не ждать пока отправиться байт адреса?

     

  8. Я понял откуда я взял неправильную интерпритацию столбцов Alternate functions и Additional functions,
    я их подсознательно перепутал со столбцами Default и Remap из датащитов из F1xx серии, а вчера начал
    делать более информативный компонент STM32F030F4 для DipTrace и случился затык.

  9. То есть ситуация что в alternate functions могут встречаться более одного варианта разводки периферии по ногам микросхемы - нормальна?

     

     

    Тогда я что то запутался - в чём смысл отдельных столбцов в таблице Alternate functions и Additional functions ?

     

    Уже ответили: http://forum.easyelectronics.ru/viewtopic.php?f=35&amp;t=38418&amp;p=591070#p591070

  10. В колонке Alternate functions должно быть написано где появляется переферия по умолчанию,

    а в колонке Additional functions варианты куда её можно переназначить и там действительно

    может быть много вариантов.

  11. Вот что мне надо было:

    Спойлер

     

    
    #define F_CPU 48000000UL
    
    //----------------------------------------настройка SysTick---------------------------------------------------------------------
    
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; //ставим бит номер 0 в 0 (на всякий случай) //т.е. не используем прерывания
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; //SysTick_CTRL_TICKINT_Msk - включаем тактирование от HCLK//SysTick_CTRL_ENABLE_Msk - включаем таймер SysTick
        
    //-------------------------------------------------------------------------------------------------------------------------------    
    
    void _delay_us(uint16_t us)
    {
    //////////////////////////////////////////////////////////////////////////////////////////////    
    SysTick->LOAD = ((F_CPU/1000000)*us)-30;    //загружаем число тактов ожидания (не более 2^24)// 30 - вычитание тактор накладных    расходов
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //включаем таймер SysTick
        
    while(0x00 == (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) {}    //0x10000 - бит номер 16 //SysTick_CTRL_COUNTFLAG_Msk //(uint32_t)0x10000U
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //выключение таймер SysTick
    //////////////////////////////////////////////////////////////////////////////////////////////
    }
    
    void _delay_ms(uint16_t ms)
    {
    //////////////////////////////////////////////////////////////////////////////////////////////
    while(ms)    
      {
        ms--;    
      _delay_us(1000);
      }
    //////////////////////////////////////////////////////////////////////////////////////////////    
    }

     

     


     

    можете предложить как сэкономить байт другой флеша или оперативки, а также предложить научно обоснованную
    поправку вместо "30" , она явно великовата, но ЛА  через ногодрыг PB1 трудно понять погрешности
    самого ногодрыга.

    На DWT всё это было технически совершенней  особенно нравилась что первой строкой:

    DWT->CYCCNT = 0; //Обнуляем счетчик
     
    начинался отсчёт и поправка требовалась меньше.

  12. Чем заменить DWT на STM32F030F4 для задержек delay_us и delay_ms ?
    На STM32F105RBT6 замечательно работало так:

    Спойлер

     

     

    
    #define F_CPU 72000000UL
    
    //--------------------------------------------------------------------------------------------
    
    {//настройка DWT
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // Включаем TRACE
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // Разрешаем DWT счетчик    
    }
    
    //--------------------------------------------------------------------------------------------
    
    void _delay_us(uint16_t us)
    {
    //////////////////////////////////////////////////////////////////////////////////////////////
    DWT->CYCCNT = 0; //Обнуляем счетчик    
    if (0x00 == us)    return;
    uint32_t period = 0;
    period = ((F_CPU/1000000)*us)-17;      //17 подобранныq коэфициент в ЛА для STM32F105RB 72мГц ядро, 50мГц порт     
    while(DWT->CYCCNT < period){}    
    //////////////////////////////////////////////////////////////////////////////////////////////
    }
    void _delay_ms(uint16_t ms)
    {
    //////////////////////////////////////////////////////////////////////////////////////////////
    DWT->CYCCNT = 0; //Обнуляем счетчик        
    uint32_t period = 0;    
    period = ((F_CPU/1000)*ms)-17;  //17 подобранныq коэфициент в ЛА для STM32F105RB 72мГц ядро, 50мГц порт         
    while(DWT->CYCCNT < period){}    
    //////////////////////////////////////////////////////////////////////////////////////////////    
    }

     

     

     

    Можно ли использовать SysTick без прерываний, если можно, то как это сделать на CMSIS (под Keil 5.26) ?
    Если нельзя, то как это сделать на CMSIS на самом, по вашему мнению, ненужном таймере STM32F030F4?

  13. Я точно сам не знаю что я тут включаю, скопипастил откуда то.

    На другом форуме ответили (http://forum.easyelectronics.ru/viewtopic.php?f=35&amp;t=38368&amp;p=590328#p590328)

    , такой код заработал:

    FLASH->ACR = FLASH_ACR_LATENCY;
    
    // настраиваем систему тактирования
    RCC->CR |= RCC_CR_HSEON;  //включаем генератор HSE
    while(!(RCC->CR & RCC_CR_HSERDY));  //ожидание готовности HSE
    RCC->CFGR2 = RCC_CFGR2_PREDIV_DIV1;  // предделитель для PLL
    RCC->CFGR = RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_PLLMUL6;  // настройка PLL
    RCC->CR |= RCC_CR_PLLON;  //включаем PLL
    while(!(RCC->CR & RCC_CR_PLLRDY));  //ожидание готовности PLL
    RCC->CFGR |= RCC_CFGR_SW_PLL;  // настраиваем делители шин и переводим тактирование от PLL

     

  14. Как настроить тактирование STM32F030F4 через CMSIS на максимальные частоты от кварца 8мгц, как на скрине от CubeMX ?

    Вот так работает не на 48мгц а на 8мгц (засекал по частоте срабатывания таймера TIM3 т.к. частоту 48мгц мерить нечем,

    TIM3 срабатывает через 3сек а не через 0,5сек):

     

    Спойлер

     

     

    
    {//настройка тактирования
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    //************************************************************************************************************
    RCC->CR |= RCC_CFGR_SW_HSE;  //сброс //RCC_CFGR_SW_HSE (0x00000001U) //!< HSE selected as system clock // 
    	
    /* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
    /* Enable HSE */
    RCC->CR |= ((uint32_t)RCC_CR_HSEON);
    /* Wait till HSE is ready and if Time out is reached exit */
    do
    {
     HSEStatus = RCC->CR & RCC_CR_HSERDY;
     StartUpCounter++;
    } while((HSEStatus == 0) && (StartUpCounter != 0x1000)); 
    
    if ((RCC->CR & RCC_CR_HSERDY) != RESET) HSEStatus = (uint32_t)0x01;
    else HSEStatus = (uint32_t)0x00;
    
    if (HSEStatus == (uint32_t)0x01)
    {
     /* Enable Prefetch Buffer and set Flash Latency */
     FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
     /* HCLK = SYSCLK:16 */
     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
     /* PCLK = HCLK */
     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
     /* PLL configuration = HSE * 2 = 24 MHz */
     //RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMUL));  
     //RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL2); 
     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE_PREDIV | RCC_CFGR_PLLXTPRE_HSE_PREDIV_DIV1 | RCC_CFGR_PLLMUL6);
     /* Select HSE as system clock source */
     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;
    
     /* Wait till PLL is used as system clock source */
     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_HSE)
     {
     }
    }
    RCC->CR &= (uint32_t)~(0x00000001);
    RCC->CR &= ~RCC_CR_PLLON;	
    	
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////	
    }	
    
    {//настройка таймеров
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    //---------------------------------------------------TIM3----------------------------------------------------------------------
    NVIC_SetPriority(TIM3_IRQn, 1); //Приоритет прерывания таймера 3
    NVIC_EnableIRQ(TIM3_IRQn); //Разрешаем обработку прерывания от таймера 3
    
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;//Включаем тактирование таймера TIM3
    TIM3->PSC = 48000; //Настройка предделителя таймера (1ms при 48мгц)
    TIM3->ARR = 500;  //Загружаем число миллисекунд в регистр автоперезагрузки
    TIM3->DIER |= TIM_DIER_UIE; //Разрешаем прерывание при переполнении счетчика
    TIM3->CR1 |= TIM_CR1_CEN;//Запускаем счет	
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	
    }
    
    extern "C" void TIM3_IRQHandler(void)
    {
    ///////////////////////////////////////////////////////////////////////////	
    TIM3->SR &= ~TIM_SR_UIF; //Clean UIF Flag
    	
    bibip(50,2000);	//пищим пищалкой  50mc на 2000гц
    	
    ///////////////////////////////////////////////////////////////////////////	
    }	

     

     

    Что не так?

     

     

    Безымянный.png

  15. Начал делать проект под STM32F030F4 и обнаружил что не могу подключить к проекту Standard Peripherals Drivers  стандартными средствами,

    так ка я это делал для серии F1 (см. скрин из проекта от F1), там такой строки просто нет!

    Как добавить "Standard Peripherals Drivers" для F0 в Keil 5.26?

    Были ли вообще когда либо сразу в  Keil  библиотеки "Standard Peripherals Drivers" для серии F0 ?

    Безымянный.png