Где то ещё i2c код был, емли нужно - завтра найду.
Я такое не скоро написал бы ![]()
Простой пример как использовать еще можно?
Что не так? То что не с нуля?
таймер 32 битный а диапазон как у 16 битного
опять в лужу?
прескалер от регистра перезагрузки не отличаешь?
Мне надо было для сохранения параметров.
Соответственно там всего две функции, запись параметра и чтение параметра.
void FLASH_write_param(unsigned short numParam, unsigned long paramValue);
unsigned long FLASH_read_param(unsigned short numParam);
Номер параметра 16 битный, само значение параметра 32х битное.
Я думал, что у 32х битного таймера шире диапазон прескалера. Хотя, наверное, просто «гоню» ![]()
NumParam - это адрес в странице флэша? Или что? Какой диапазон значений?
Номер параметра, это номер параметра, в адрес преобразуется само, не надо об этом думать.
Ну например это частота fm радиостанции в запрограммированных каналах, соответственно номер параметра это номер станции, значение параметра - частота.
Впрочем для радио я этот код и писал.
Ага, понял. Большое спасибо за разъяснение!
вот откопал код от 20 года, общее понимание работы с I2C через CMSIS можно почерпнуть.
Спойлер
//eeprom.h // модуль работы с EEPROM
#ifndef EEPROM_H
#define EEPROM_H
#define EEPROM_OWN_ADDRESS 0x50 // адрес I2C устройства - меняется пинами на 24LC64
#define EEPROM_PAGE_SIZE 32 // размер страницы для записи и чтения - из даташита на чип
#define EEPROM_START_TXT_DATA 4096 // начальный адрес для текстовых данных об MQTT сервере
void initEEPROMi2c(void); // инициализация шины I2C
void readEEPROMallDATA(void); // чтение из EEPROM 24LC64 данных о MQTT серверах
#endif /* EEPROM_H */
//eeprom.c // модуль работы с EEPROM
#include "stm32f30x.h"
#include "dmfcomm.h"
#include "dmfuart.h"
#include <string.h>
#include "eeprom.h" // заголовочный файл со всеми константами
// http://arduino.ru/forum/otvlechennye-temy/programmirovanie-32-kh-razryadnykh-mk?page=20
unsigned char eeprom_buf[EEPROM_PAGE_SIZE]; // буфер чтения/записи страницы
#define CLEAR_EEPROM_BUF memset(eeprom_buf,0,EEPROM_PAGE_SIZE) // офистка буфера
unsigned long timerEEPROMpause; // таймер паузы для задержки между операциями
void delayEEPROM5msec(void) { // согласно даташиту, после любой записи в EEPROM необходимо подождать минимум 5 миллисекунд для следующей операции
while ((current_millis - timerEEPROMpause) < 5UL); // если прошло 5 и более мсек - выходим
}
unsigned short getAddressFromNumBlock(const unsigned short numBlock) { // преобразует номер блока/страницы (так удобнее считать)
return ((EEPROM_PAGE_SIZE * numBlock) + EEPROM_START_TXT_DATA); // возвращает физический адрес начала блока
}
unsigned char eeprom_read(const unsigned short address) { // чтение одного байте
delayEEPROM5msec(); // ждем если вдруг что то в EEPROM записывали
unsigned char temp=0; // временная переменная
I2C1->CR2 = (2<<16) | (EEPROM_OWN_ADDRESS<<1); // адрес чипа со сдвигом влево и прописываем количество отправлемых байт NBYTES = 2
while (!(I2C1->ISR & I2C_ISR_TXE) ); // ждем как шина освободится
I2C1->TXDR = (unsigned char) (address>>8); /* Byte to send */ // отправлем в шину старший байт адреса EEPROM
I2C1->CR2 |= I2C_CR2_START; /* Go */ // запускаем
while (!(I2C1->ISR & I2C_ISR_TXIS) ); // ждем освобождения регистра данных
I2C1->TXDR = (unsigned char) (address &0x00FF); /* Byte to send */ // отправляем в гину младший байт адреса EEPROM
while (!(I2C1->ISR & I2C_ISR_TC) ){}; // ждем окончания отправки
I2C1->CR2 = I2C_CR2_AUTOEND | (1<<16) | (EEPROM_OWN_ADDRESS<<1) | I2C_CR2_RD_WRN | I2C_CR2_NACK; // автоокончание приема,1 байт принять, адрес со сдвигом, режим приема, без флага ACK
I2C1->CR2 |= I2C_CR2_START; /* Go */ // даем команду начала приема
while (!(I2C1->ISR & I2C_ISR_RXNE) ){}; // ждем как прилетит байт
temp = I2C1->RXDR; // читаем принятый байт из регистра
return temp; // возвращаем его
}
void eeprom_write(const unsigned short address, const unsigned char data) { // запись одно байте в eeprom
delayEEPROM5msec();
I2C1->CR2 = I2C_CR2_AUTOEND | (3<<16) | (EEPROM_OWN_ADDRESS<<1);
while (!(I2C1->ISR & I2C_ISR_TXE) ); /* Check Tx empty */
I2C1->TXDR =(unsigned char) (address>>8); /* Byte to send */
I2C1->CR2 |= I2C_CR2_START; /* Go */
while (!(I2C1->ISR & I2C_ISR_TXIS) );
I2C1->TXDR = (unsigned char) (address &0x00FF); /* Byte to send */
while (!(I2C1->ISR & I2C_ISR_TXIS) ); // дожидаемся окончания отправки адреса
I2C1->TXDR = data ; /* Byte to send */ // и отправляем байт
timerEEPROMpause = current_millis; // обнуляем таймер ожидания следующей операции
}
void eeprom_pageclear(const unsigned short address, const unsigned char nbytes) { // очистка страницы
delayEEPROM5msec();
I2C1->CR2 = I2C_CR2_AUTOEND | ((2+nbytes)<<16) | (EEPROM_OWN_ADDRESS<<1); // все аналогично отправке одного байта, только количество прописываем размер страницы +2
while (!(I2C1->ISR & I2C_ISR_TXE) ); /* Check Tx empty */
I2C1->TXDR =(unsigned char) (address>>8); /* Byte to send */
I2C1->CR2 |= I2C_CR2_START; /* Go */
while (!(I2C1->ISR & I2C_ISR_TXIS) );
I2C1->TXDR = (unsigned char)(address &0x00FF); /* Byte to send */
for(unsigned char index=0;index<=nbytes-1;index++) { // цикл по количеству отправляемых байт
while (!(I2C1->ISR & I2C_ISR_TXIS) ); // ждем как очистится регистр
I2C1->TXDR = 0 ; /* Byte to send */ // пишем нули
}
timerEEPROMpause = current_millis;
}
void eeprom_pagewrite(const unsigned short address, const unsigned char *buf, const unsigned char nbytes) {
delayEEPROM5msec();
I2C1->CR2 = I2C_CR2_AUTOEND | ((2+nbytes)<<16) | (EEPROM_OWN_ADDRESS<<1); // все аналогично отправке одного байта, только количество прописываем размер страницы +2
while (!(I2C1->ISR & I2C_ISR_TXE) ); /* Check Tx empty */
I2C1->TXDR =(unsigned char) (address>>8); /* Byte to send */
I2C1->CR2 |= I2C_CR2_START; /* Go */
while (!(I2C1->ISR & I2C_ISR_TXIS) );
I2C1->TXDR = (unsigned char)(address &0x00FF); /* Byte to send */
for(unsigned char index=0;index<=nbytes-1;index++) { // цикл по буферу
while (!(I2C1->ISR & I2C_ISR_TXIS) );
I2C1->TXDR = buf[index] ; /* Byte to send */ // отправляем из буфера
}
timerEEPROMpause = current_millis;
}
void eeprom_pageread(const unsigned short address, unsigned char* buf, const unsigned char nbytes) {
delayEEPROM5msec();
I2C1->CR2 = (2<<16) | (EEPROM_OWN_ADDRESS<<1); // отправляем два байта адреса
while (!(I2C1->ISR & I2C_ISR_TXE) );
I2C1->TXDR = (unsigned char) (address>>8); /* Byte to send */
I2C1->CR2 |= I2C_CR2_START; /* Go */
while (!(I2C1->ISR & I2C_ISR_TXIS) );
I2C1->TXDR = (unsigned char)(address &0x00FF); /* Byte to send */
while (!(I2C1->ISR & I2C_ISR_TC) ){};
I2C1->CR2 = I2C_CR2_AUTOEND | (nbytes<<16) | (EEPROM_OWN_ADDRESS<<1) | I2C_CR2_RD_WRN | I2C_CR2_NACK; // читаем nbytes байт
I2C1->CR2 |= I2C_CR2_START; /* Go */
for(unsigned char index=0;index<=nbytes-1;index++) { // цикл по буферу
while (!(I2C1->ISR & I2C_ISR_RXNE) ){}; // ждем как появится байт
buf[index] = I2C1->RXDR ; // читаем его в буфер
}
}
void initEEPROMi2c(void) { // инициализация шины I2C
// I2C1 SCL PB8
GPIOB->MODER |= GPIO_MODER_MODER8_1; // 10 — режим альтернативной функции.
GPIOB->MODER &= ~GPIO_MODER_MODER8_0; // 10 — режим альтернативной функции.
GPIOB->OTYPER |= GPIO_OTYPER_OT_8; // 1 - open-drain
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR8_1; // 01 — подтяжка к плюсу питания или pull-up сокращено PU
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR8_0; // 01 — подтяжка к плюсу питания или pull-up сокращено PU
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8_1; // 11 — 50 MHz
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8_0; // 11 — 50 MHz
GPIOB->AFR[1] |= (0x04); // Назначаем PB8 выводу альтернативную функцию AF4
// I2C1 SDA PB9
GPIOB->MODER |= GPIO_MODER_MODER9_1; // 10 — режим альтернативной функции.
GPIOB->MODER &= ~GPIO_MODER_MODER9_0; // 10 — режим альтернативной функции.
GPIOB->OTYPER |= GPIO_OTYPER_OT_9; // 1 - open-drain
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR9_1; // 01 — подтяжка к плюсу питания или pull-up сокращено PU
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR9_0; // 01 — подтяжка к плюсу питания или pull-up сокращено PU
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9_1; // 11 — 50 MHz
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9_0; // 11 — 50 MHz
GPIOB->AFR[1] |= (0x04 << 4); // Назначаем PB9 выводу альтернативную функцию AF4
// I2C1 init
I2C1->CR1 = 0; // обнуляем все статусы
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // включаем тактирование
RCC->CFGR3 |= RCC_CFGR3_I2C1SW;
I2C1->TIMINGR = 0x2000090E; // таймеры - скорость шины 400 кГц
I2C1->OAR1 = 0;
I2C1->OAR2 = 0;
I2C1->CR1 = I2C_CR1_PE; // включаем I2C
timerEEPROMpause = 0UL;
}
void readEEPROMallDATA(void) { // чтение из EEPROM 24LC64 данных о MQTT серверах
#ifdef SAVE_EEPROM // если надо записать данные в EEPROM
// save data to eeprom
for(unsigned char i=0; i<9; ++i) eeprom_pageclear(getAddressFromNumBlock(i), EEPROM_PAGE_SIZE); // clear eeprom // очищаем EEPROM нулями
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttDeviceID); eeprom_pagewrite(getAddressFromNumBlock(0),eeprom_buf , EEPROM_PAGE_SIZE); // записываем поблочно
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttServer1); eeprom_pagewrite(getAddressFromNumBlock(1),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttServer2); eeprom_pagewrite(getAddressFromNumBlock(2),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttPort1); eeprom_pagewrite(getAddressFromNumBlock(3),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttPort2); eeprom_pagewrite(getAddressFromNumBlock(4),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttUser1); eeprom_pagewrite(getAddressFromNumBlock(5),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttUser2); eeprom_pagewrite(getAddressFromNumBlock(6),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttPass1); eeprom_pagewrite(getAddressFromNumBlock(7),eeprom_buf , EEPROM_PAGE_SIZE);
CLEAR_EEPROM_BUF; strcpy((char *)eeprom_buf, (char *)strMqttPass2); eeprom_pagewrite(getAddressFromNumBlock(8),eeprom_buf , EEPROM_PAGE_SIZE);
#endif
// read data from eeprom
memset(mqttDeviceID,0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(0),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttDeviceID, (char *)eeprom_buf); // читаем поблочно данные в переменные
memset(mqttServer[0],0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(1),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttServer[0], (char *)eeprom_buf);
memset(mqttServer[1],0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(2),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttServer[1], (char *)eeprom_buf);
memset(mqttPort[0],0,max_size_mqtt_port); eeprom_pageread(getAddressFromNumBlock(3),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttPort[0], (char *)eeprom_buf);
memset(mqttPort[1],0,max_size_mqtt_port); eeprom_pageread(getAddressFromNumBlock(4),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttPort[1], (char *)eeprom_buf);
memset(mqttUser[0],0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(5),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttUser[0], (char *)eeprom_buf);
memset(mqttUser[1],0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(6),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttUser[1], (char *)eeprom_buf);
memset(mqttPass[0],0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(7),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttPass[0], (char *)eeprom_buf);
memset(mqttPass[1],0,max_size_mqtt_device); eeprom_pageread(getAddressFromNumBlock(8),eeprom_buf , EEPROM_PAGE_SIZE); strcpy((char *)mqttPass[1], (char *)eeprom_buf);
}
А разницы нет что у тебя используется F30x, что у меня F103 ?
разница конечно же есть, но надо просто сравнить DS / имена регистров / подправить, в среднем все очень похоже.
Много раз уже переносил наработки с F303 на F103 или F411.
попался неплохой сайт про стм-ы
А если через putty?
а он умеет? никогда бы не подумал, это же не COM Порт.


