20. STM32. Програмування STM32F103. I2C Slave
У попередній статті ми розглянули роботу STM32 з шиною I2C у якості Майстра. Тобто, він був ведучий і опитував сенсор. Тепер зробимо так, щоб STM32 був Slave-ом і відповідав на запити, тобто сам працював як сенсор. Ми виділимо 255 байт пам`яті під регістри з адресами від 0 до 0xFF, і дозволимо Майстру в них писати/читати. А щоб приклад був не таким примітивним, зробимо з нашого STM32, ще і аналого-цифровий перетворювач з інтерфейсом I2C. ADC буде обробляти 8 каналів. Результати перетворень контролер буде віддавати Майстру при читанні з регістрів. Оскільки результат перетворення ADC займає 12 біт, нам потрібно буде 2 регістра (2 байта) на кожний канал ADC.
Весь функціонал який стосується I2C знаходиться у файлах i2c_slave.h, i2c_slave.c. Скачати приклад можна тут: STM32. Скачати приклади
i2c_slave.h містить налаштування:
I2CSLAVE_ADDR - адреса нашого пристрою; ADC_ADDR_START - початкова адреса регістрів, які відповідають за результати перетворень ADC.
У файлі i2c_slave.c нас більш за все цікавлять функції get_i2c1_ram та set_i2c1_ram. Функція get_i2c1_ram відповідає за зчитування даних з регістрів. Вона повертає дані з зазначеної адреси, які віддаються Майстру. У нашому випадку дані зчитуються з масиву i2c1_ram, але, якщо Майстер запитує адреси регістрів з діапазону відведеного для результатів ADC, то відправляються дані перетворень ADC.
get_i2c1_ram:
uint8_t get_i2c1_ram(uint8_t adr) {
//ADC data
if ((ADC_ADDR_START <= adr) & (adr < ADC_ADDR_START + ADC_CHANNELS*2)) {
return ADCBuffer[adr - ADC_ADDR_START];
}
else {
// Other addresses
return i2c1_ram[adr];
}
}
Функція set_i2c1_ram - записує дані прийняті від Майстра у регістри з вказаною адресою. В нашому випадку дані просто записуються у масив i2c1_ram. Але це не обов`язково. Ви можете, наприклад, додати перевірку, і, коли на певну адресу приходить певне число, виконати якісь дії. Таким чином, Ви зможете подавати різні команди мікроконтролеру.
set_i2c1_ram:
void set_i2c1_ram(uint8_t adr, uint8_t val) {
i2c1_ram[adr] = val;
return;
}
Ініціалізація досить проста:
int main(void)
{
SetSysClockTo72();
ADC_DMA_init();
I2C1_Slave_init();
while(1)
{
}
}
Спочатку ми встановлюємо максимальну частоту роботи контролера. Максимальна швидкість необхідна, коли треба уникнути будь-яких затримок на шині I2C. Потім запускаємо роботу ADC з використанням DMA. Про ADC читайте тут . Про DMA читайте тут. І, насамкінець, виконуємо ініціалізацію шини I2C як Slave. Як бачите, нічого складного.
Тепер підключимо наш модуль STM32 до Raspberry Pi. До каналів ADC підключимо потенціометри. І будемо зчитувати з нашого контролера показники ADC. Не забуваємо, що для роботи шини I2C потрібно на кожну лінію шини встановити підтягуючі резистори.
У консолі Raspberry перевіримо чи взагалі видно наш пристрій на шині I2C (про те, як використовувати шину I2C на Raspberry читайте тут):
i2cdetect -y 1
Як бачите, адреса пристрою 0x27, хоча ми вказали 0x4E. Як матимете час, подумайте - чому так сталося.
Для зчитування з регістрів I2C-Slave приладу виконуємо команду:
i2cget -y 1 0x27 0x00
Де: 0x27 - адреса пристрою, 0x00 - адреса регістру (0x00...0xFF).
Для запису у регістри I2C-Slave приладу виконуємо команду:
i2cset -y 1 0x27 0xA0 0xDD
Де: 0x27 - адреса пристрою, 0xA0 - адреса регістру 0xDD -8-bit дані (0x00...0xFF)
Попередня команда записала число 0xDD у регістр 0xA0 (писати у перші 16 регістрів можна, та сенсу немає, по вони відведені під ADC). Тепер прочитаємо:
i2cget -y 1 0x27 0xA0
Щоб спростити процес зчитування даних ADC каналів я написав скрипт:
#!/usr/bin/env python
import smbus
import time
bus = smbus.SMBus(1)
address = 0x27
while (1):
ADC = {};
for i in range(0, 8):
LBS = bus.read_byte_data(address, 0x00+i*2)
MBS = bus.read_byte_data(address, 0x00+i*2+1)
ADC[i] = MBS*256 + LBS
print ADC
time.sleep(0.2)
Він опитує і виводить у консоль результати усіх 8-ми ADC-каналів.
Аналогічним чином можна об`єднати декілька мікроконтролерів. Один з них має бути Master (дивись попередню статтю), інші Slave.
Бажаю успіхів!
Дивись також:
- 1. STM32. Програмування STM32F103. Тестова плата. Прошивка через UART та через ST-Link
- 2. STM32. Програмування. IDE для STM32
- 3. STM32. Програмування STM32F103. GPIO
- 4. STM32. Програмування STM32F103. Тактування
- 5. STM32. Програмування STM32F103. USART
- 6. STM32. Програмування STM32F103. NVIC
- 7. STM32. Програмування STM32F103. ADC
- 8. STM32. Програмування STM32F103. DMA
- 9. STM32. Програмування STM32F103. TIMER
- 10. STM32. Програмування STM32F103. TIMER. Захоплення сигналу
- 11. STM32. Програмування STM32F103. TIMER. Encoder
- 12. STM32. Програмування STM32F103. TIMER. PWM
- 13. STM32. Програмування STM32F103. EXTI
- 14. STM32. Програмування STM32F103. RTC
- 15. STM32. Програмування STM32F103. BKP
- 16. STM32. Програмування STM32F103. Flash
- 17. STM32. Програмування STM32F103. Watchdog
- 18. STM32. Програмування STM32F103. Remap
- 19. STM32. Програмування STM32F103. I2C Master
- 20. STM32. Програмування STM32F103. I2C Slave
- 21. STM32. Програмування STM32F103. USB
- 22. STM32. Програмування STM32F103. PWR
- 23. STM32. Програмування STM32F103. Option bytes
- 24. STM32. Програмування STM32F103. Bootloader
- STM32. Скачати приклади
- System Workbench for STM32 Інсталяція на Ubuntu
- Keil uVision5 – IDE для STM32
- IAR Workbench – IDE для STM32
- Керування безколекторним двигуном постійного струму (BLDC) за допомогою STM32
- Керування PMSM за допомогою STM32
Недавні записи
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
Tags
battery soldering java-script ngnix adc rs-232 flask esp8266 watchdog web exti solar mongodb rtc sms pwm usart books ethernet smd git websocket meteo css python dc-dc displays led ssd1306 eeprom gpio barometer max1674 mpx4115a brushless motor mpu-6050 timer sensors remap servo bldc atmega pmsm 3d-printer flash encoder examples dma raspberry-pi tim ssd1331 piezo mpu-9250 rfid eb-500 foc bme280 gps nvic dht11 bluetooth hih-4000 stm32 st-link docker uart avr html wifi bmp280 bkp nodemcu options usb lcd programmator i2c capture
Архіви