28 Сен., 2021, 00:28

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


Учебно - развлекательная

Автор zenon, 05 Нояб., 2020, 17:19

« предыдущая - следующая »

zenon

Отвлекаемся от "серьёзных" тем, в целях обучения и развлечения, и схем "выходного дня".
Сыну 15. Кое-что уже сделано, по мере свободного времени что-то творим.
Сейчас в планах по быстрому rda5807m + pro mini, усилитель с темброблоком мы уже сделали, и даже разместили в корпус от коммутатора д-линк.
Схема в аттаче - делали летом, немнго не в тему раздела, но оно пересекается, УНЧ - ВЭФ260 - схема мелькала на коте.
Весь проект с платой если надо выложу, но он сделан на скорую руку, нам нужен был опыт пайки больше.
Библиотека для приемника есть тут.

++
Ну и на очереди вот эти часы, всё уже есть, кроме своей платы под свои элементы, и датчик надо сделать.

zenon


Slabovik

Занятная вещица, но ведь хочется подробностей, так сказать, от первых лиц :)
Ардуиновскую библиотеку готовую, похоже, использовали, не изобретали?
Экранчик, управление?
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Эммм... тут просто скетч для дуины который пишет в регистры rda5807m частоту настройки радиоприёмника по i2c.
Ни экранчика, ни управления. :)
Как вариант находил управление по uart, вэб-морду...
Сама микросхема-то известная и вариантов препараций её много.
#include <Wire.h>              // I2C-Library

double f_ini=102.6;            // Стартовая частота настройки приемника. (Изменяем на нужную).

void setup()                    // Инициализация.
{
  Wire.begin();                // Инициализация двухпроводной шины I2C.
  setFrequency(f_ini);          // Вызываем фукнкцию загрузки частоты настройки в модуль EM5807M.
}

void loop()                    // Основной цикл программы
{
  // Здесь можем написать нашу самую лучшую программу, которая будет работать так как нам нужно.
}
 

void setFrequency(double fmhz)  // Функция загрузки частоты настройки в модуль EM5807M.
{
  int  frequencyB = 4 * (fmhz * 1000000 + 225000) / 32768;
  char frequencyH = frequencyB >> 8;    // Старший байт.
  char frequencyL = frequencyB & 0XFF;  // Накладываем маску 0xFF на младший байт.
  Wire.beginTransmission(0x60);          // Адрес чипа RDA5807M
  Wire.write(frequencyH);                // Старший байт.
  Wire.write(frequencyL);                // Младший байт.
  Wire.write(0xB8);                      // 1011 1000    =Стерео
  Wire.write(0x10);                      // 0001 0000
  Wire.write((byte)0x00);                //
  Wire.endTransmission();                // формируем I2C-Stop.
}
Отсюда.
Вот ещё.
И вот этот материал уже интереснее.
Ну и на коте есть проект.

zenon

Управление rda5807m от stm32f0, перебор забитых в массив станций двумя кнопками на PA4, PA5, i2c на PB6 и PB7.
#include <stm32f0xx.h>
static uint16_t R2H = 0, R3H = 0, R4H = 0, R5H = 0, R6H = 0, R7H = 0, R0AH = 0;
#define CHAN_SHIFT 6
#define FDEL 100
#define RDA5807_OWN_ADDRESS (0x11) // адрес произвольного доступа (порегистровый) I2C_INDX //I2C-Address RDA Chip for Index  Access
//  0x10 // I2C-Address RDA Chip for sequential  Access
//  0x11 // I2C-Address RDA Chip for Index  Access
#define nop()  __NOP()
#define pin_toggle(gpioport, gpios)  do{  \
    register uint32_t __port = gpioport->ODR;  \
    gpioport->BSRR = ((__port & gpios) << 16) | (~__port & gpios);}while(0)
#define pin_set(gpioport, gpios)  do{gpioport->BSRR = gpios;}while(0)
#define pin_clear(gpioport, gpios) do{gpioport->BSRR = ((gpios) << 16);}while(0)
#define pin_read(gpioport, gpios) (gpioport->IDR & (gpios) ? 1 : 0)
#define pin_write(gpioport, gpios)  do{gpioport->ODR = gpios;}while(0)

uint16_t fm_freq_vlg[] = {
  0,
 949, // 0 Радио 7 на семи холмах
 961, // 1 Love Radio
 965, // 2 Комсомольская правда
 972, // 3 Наше радио
 976, // 4 Радио дача
 983, // 5 Радио России
 988, // 6 Радио Energy
 992, // 7 Радио Maximum
1006, // 8 Europa +
1011, // 9 Эхо Москвы
1015, //10 Волгоград FM
1020, //11 Новая Волна
1026, //12 Ретро FM
1031, //13 Авторадио
1036, //14 Дорожное радио
1040, //15 Новое радио
1045, //16 Юмор FM
1051, //17 Радио Спутник
1056  //18 Русское радио
};

char station = 0;
static volatile uint64_t ticks = 0;
uint32_t lticks = 0;
void systick_init(void);
void gpio_init(void);
void i2c_init(void);
void rda5807_write16_reg(uint8_t reg, uint16_t data);
void rda5807_send_reg(uint8_t reg, uint8_t data_h,uint8_t data_l);
uint16_t rda5807_read16_reg(uint8_t reg);
void rda5807_init(uint16_t frequency, char volume, char delay);
void nop_delay(unsigned int i);


int main(void) {
  SystemInit();
  systick_init();
  gpio_init();
  i2c_init();
  rda5807_init(fm_freq_vlg[17], 15, 1);
  while (1) {
    // опрос кнопок раз в 20 ms
    if(lticks > ticks || ticks - lticks > 20) {
      // следующая станция
      if (!pin_read(GPIOA, 1<<4)) {
        if (station > 19) station = 0;
        station++;
        rda5807_init(fm_freq_vlg[station], 15, 1);
      }
      if (!pin_read(GPIOA, 1<<5)) {
        if (station < 1) station = 19; else station--;
        rda5807_init(fm_freq_vlg[station], 15, 1);
      }
    }
  }
} // main(void)

void SysTick_Handler(void) {
  ticks++;
}

void systick_init(void) {
  SystemCoreClockUpdate(); // Make sure SystemCoreClock is up-to-date
  SysTick->LOAD = (SystemCoreClock / 1000) - 1;
  SysTick->VAL = 0;
  SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}

void gpio_init(void) {
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // включили переферию A
  RCC->AHBENR  |= RCC_AHBENR_GPIOBEN; // B
  // Кнопки на PA4 PA5
  GPIOA->PUPDR = GPIO_PUPDR_PUPDR4_0; // PA4 как вход с подтяжкой вверх
  GPIOA->PUPDR = GPIO_PUPDR_PUPDR5_0; // PA5

}


void nop_delay(unsigned int i) {
  for (; i>0; i--) {
    for (int j = 0; j < FDEL; ++j) {
      __asm__ __volatile__("nop\n\t":::"memory");
    }
  }
}

void i2c_init(void) {
  //RCC->AHBENR  |= RCC_AHBENR_GPIOBEN; в gpio_init
       
  RCC->APB1ENR  |= RCC_APB1ENR_I2C1EN;
  RCC->CFGR3    |= RCC_CFGR3_I2C1SW;

  GPIOB->AFR[0] |=  (1<<(4*6)) | (1<<(4*7));
  GPIOB->MODER  &= ~(GPIO_MODER_MODER6  | GPIO_MODER_MODER7  );    // PB6 и PB7
  GPIOB->MODER  |=  (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);
  GPIOB->OTYPER |=  (GPIO_OTYPER_OT_6    | GPIO_OTYPER_OT_7  );
       
  I2C1->TIMINGR = (uint32_t)0x00B01A4B;
  I2C1->CR1 = I2C_CR1_PE;
}
// RDA5807                  STM32F0
// бело-серый  SCL/CLK      PB6      линия тактирования
// черный      SDA/DIO      PB7      линия данных

void rda5807_write16_reg(uint8_t reg, uint16_t data) {
  I2C1->CR2 =  I2C_CR2_AUTOEND | (3<<16) | (RDA5807_OWN_ADDRESS<<1);

  while (!(I2C1->ISR & I2C_ISR_TXE)); // Check Tx empty

  I2C1->TXDR = reg; // Byte to send
  I2C1->CR2 |= I2C_CR2_START; // Go

  while (!(I2C1->ISR & I2C_ISR_TXIS));
  I2C1->TXDR = (uint8_t)(data>>8); // Byte to send
 
  while (!(I2C1->ISR & I2C_ISR_TXIS));
  I2C1->TXDR = (uint8_t)(data &0x00FF); // Byte to send
}

void rda5807_send_reg(uint8_t reg, uint8_t data_h,uint8_t data_l) {
  I2C1->CR2 =  I2C_CR2_AUTOEND | (3<<16) | (RDA5807_OWN_ADDRESS<<1);

  while (!(I2C1->ISR & I2C_ISR_TXE)); // Check Tx empty
  I2C1->TXDR = reg; // Byte to send
  I2C1->CR2 |= I2C_CR2_START; // Go

  while (!(I2C1->ISR & I2C_ISR_TXIS));
  I2C1->TXDR = data_h; // Byte to send
 
  while (!(I2C1->ISR & I2C_ISR_TXIS));
  I2C1->TXDR = data_l; // Byte to send
}

uint16_t rda5807_read16_reg(uint8_t reg) {
  uint16_t temp=0;
  I2C1->CR2 =  (1<<16) | (RDA5807_OWN_ADDRESS<<1);
  while (!(I2C1->ISR & I2C_ISR_TXE));
  I2C1->TXDR = reg; // Byte to send
  I2C1->CR2 |= I2C_CR2_START; // Go
  while (!(I2C1->ISR & I2C_ISR_TC)){};
  I2C1->CR2 =  I2C_CR2_AUTOEND | (2<<16) |
                (RDA5807_OWN_ADDRESS<<1) |
                          I2C_CR2_RD_WRN |
                            I2C_CR2_NACK;
  I2C1->CR2 |= I2C_CR2_START; // Go
  while (!(I2C1->ISR & I2C_ISR_RXNE)){};
  temp  = (uint16_t)(I2C1->RXDR <<8);
  while (!(I2C1->ISR & I2C_ISR_RXNE)){};
  temp |=  (uint16_t)I2C1->RXDR;
  return temp;
}

void rda5807_init(uint16_t frequency, char volume, char delay) {
  if (delay==1) nop_delay(4000);
 
  // R2H = 0, R3H = 0, R4H = 0, R5H = 0, R7H = 0, R0AH = 0;
  // R2H = 0;    0b0000000000000000
  // R2H = R2H | 0b1000000000000000  DHIZ;
  // R2H = R2H | 0b1000000000000001  ENABLE;

  // регистр 02H
  // DHIZ  (1<<15)
  // DMUTE (1<<14)
  // RENABLE (1<<0)
  // регистр 02H
  //
  R2H = R2H | (1<<15); // DHIZ  (1<<15)
  R2H = R2H | (1<<14); // DMUTE (1<<14)  0 mute, 1 normal operation
  R2H = R2H | (1<<0 ); // ENABLE
  R2H = R2H | (0<<13); // MONO  (0=stereo, 1=mono)
  R2H = R2H | (1<<12); // BASS  (0=disable, 1=enable bass boost)
  R2H = R2H | (0<<2 ); // NEW_METHOD (New  Demodulate Method Enable,  can  improve the receive sensitivity about 1dB)
  R2H = R2H | (0<<11); // RCLK NON-CALIBRATEMODE  0=RCLK clock is always supply 1=RCLK  clock  isnot  always  supply  when  FM work
  // Биты 6:4 CLK_MODE[2:0] кварц 000 = 32.768 он у нас и стоит, менять ничего не надо
 
  rda5807_write16_reg(0x02, R2H); // пишем регистр 02H

  // регистр 03H
  // BAND = 00 (87..108МГц), STEP = 00 (100кГц)
  // 3:2 BAND[1:0]Band Select.  00=87-108 MHz US/Europe 01=76-91 MHz Japan 10=76-108 MHz worldwide 11=65-76 MHz East Europe or 50-65MHz
  // выбор канала, зависит от BAND
  // BAND = 0: частота = интервал между каналами (кГц) * CHAN + 87.0 МГц.
  // BAND = 1 или 2: частота = интервал между каналами (кГц) * CHAN + 76.0 МГц.
  // BAND = 3: частота = интервал между каналами (кГц) * CHAN + 65.0 МГц.
  // частота 10 бит!
  R3H = (frequency - 870) << CHAN_SHIFT;  // chan = (frequency - band) << сдвиг на 6
  R3H = R3H | (1<<4);                    // TUNE после установки частоты установить TUNE бит!!

  rda5807_write16_reg(0x03, R3H);
  // регистр 05H
  R5H  = rda5807_read16_reg(0x05);
  R5H &= ~0x000F; // 0b0000000000001111
  R5H |= volume << 0; // Устанавливаем новую громкость
  rda5807_write16_reg(0x05, R5H);
}