1 (2023-11-30 12:29:18 отредактировано klause)

Тема: Простое радио Atmega8

Радио на модуле rda5807 + энкодер + дисплей на 74нс595(статическая индикация). Было желание сделать без помех от индикатора, особенно когда монтаж конечного изделия плотный.

/* 
 *
 *  Find RDA5807M code at: https://github.com/lucsmall/Arduino-RDA5807M
 *
 *  "Talking about my Arduino sketch for the RDA5807M FM Radio IC"
 *  http://youtu.be/9TegkAu96nE
 *
 *  "Connecting the RDA5807M FM Radio IC to an Arduino"
 *  https://youtu.be/2j1hX4uzkQ8
 *
 *  "Making my Arduino controlled RDA5807M FM Radio"
 *  https://youtu.be/4pZmkeqg5h8
 */

#include <Wire.h>
#include <EEPROM.h>
int dataPin = 8; //Пин подключен к DS входу 74HC595
int latchPin = 9; //Пин подключен к ST_CP входу 74HC595
int clockPin = 10; //Пин подключен к SH_CP входу 74HC595 
int  frequency,n1,n2,n3,n4;
int a,b,c,d;
uint32_t tmr1;
byte flag1=0;
/* Rotary Encoder: */
/*
const int clkPin = 5;   // clk - pin 5
const int dtPin  = 6;   //  dt - pin 6
const int swPin  = 2 ;  //  sw - pin 2
*/

int clkPin = 5;   // clk - pin 5
int dtPin = 6 ;  //  dt - pin 6
int swPin = 7 ; //  sw - pin 2



    /* Select the frequency we want to tune to by way
     * of selecting the channel for the desired frequency 
     */
uint16_t channel = EEPROM.read(0); 
    /*
     * assuming band starts at 87.0MHz (per settings below)
     * and channel spacing of 100kHz (0.1MHz) (per settings below)
     * then channel can be derived as follows:
     *  
     * channel = (<desired freq in MHz> - 87.0) / 0.1 
     *
     * which is the same as:
     * <10 x desired freq in MHz> - 870
     *   
     *  some examples:
     * channel 145 dec = 101.5 MHz
     * channel 153 dec = 102.3 MHz
     * channel 177 dec = 104.7 MHz
     * channel 193 dec = 106.3 MHz
     * channel 209 dec = 107.9 MHz
     * 191 = 106.1 Vikerraadio
     * 187 = 105.7 Klassika raadio
     */

/* address of the RDA5807 on two wire bus */
#define RDA5807M_ADDRESS  0b0010000 // 0x10

#define BOOT_CONFIG_LEN 12
#define TUNE_CONFIG_LEN 4

/* 
 *  These bytes set our initial configuration
 *  We don't bother to tune to a channel at this stage.
 *  But instead initiate a reset.
 */
uint8_t boot_config[] = {
  /* register 0x02 */
  0b11100000,
    /* 
     * DHIZ audio output high-z disable
     * 1 = normal operation
     *
     * DMUTE mute disable 
     * 1 = normal operation
     *
     * MONO mono select
     * 0 = stereo
     *
     * BASS bass boost
     * 0 = disabled
     *
     * RCLK NON-CALIBRATE MODE 
     * 0 = RCLK is always supplied
     *
     * RCLK DIRECT INPUT MODE 
     * 0 = ??? not certain what this does
     *
     * SEEKUP
     * 0 = seek in down direction
     *
     * SEEK
     * 0 = disable / stop seek (i.e. don't seek)
     */
  0b00000111,
    /* 
     * SKMODE seek mode: 
     * 0 = wrap at upper or lower band limit and contiue seeking
     *
     * CLK_MODE clock mode
     *  000 = 32.768kHZ clock rate (match the watch cystal on the module) 
     *
     * RDS_EN radio data system enable
     * 0 = disable radio data system
     *
     * NEW_METHOD use new demodulate method for improved sensitivity
     * 0 = presumably disabled 
     *
     * SOFT_RESET
     * 1 = perform a reset
     *
     * ENABLE power up enable: 
     * 1 = enabled
     */ 

  /* register 0x03 */
    /* Don't bother to tune to a channel at this stage*/
  0b00000000, 
    /* 
     * CHAN channel select 8 most significant bits of 10 in total
     * 0000 0000 = don't boher to program a channel at this time
     */

  0b00000000,
    /* 
     * CHAN two least significant bits of 10 in total 
     * 00 = don't bother to program a channel at this time
     *
     * DIRECT MODE used only when test
     * 0 = presumably disabled
     *
     * TUNE commence tune operation 
     * 0 = disable (i.e. don't tune to selected channel)
     *
     * BAND band select
     * 00 = select the 87-108MHz band
     *
     * SPACE channel spacing
     * 00 = select spacing of 100kHz between channels
     */
     
  /* register 0x04 */
  0b00001010, 
    /* 
     * RESERVED 15
     * 0
     *
     * PRESUMABLY RESERVED 14
     * 0
     *
     * RESERVED 13:12
     * 00
     *
     * DE de-emphasis: 
     * 1 = 50us de-emphasis as used in Australia
     *
     * RESERVED
     * 0
     *
     * SOFTMUTE_EN
     * 1 = soft mute enabled
     *
     * AFCD AFC disable
     * 0 = AFC enabled
     */
  0b00000000, 
    /* 
     *  Bits 7-0 are not specified, so assume all 0's
     * 0000 0000
     */
  
  /* register 0x05 */
  0b10001000, 
    /* 
     * INT_MODE
     * 1 = interrupt last until read reg 0x0C
     *
     * RESERVED 14:12 
     * 000
     *
     * SEEKTH seek signal to noise ratio threshold
     * 1000 = suggested default
     */ 
  
  0b00001111, 
    /* 
     * PRESUMABLY RESERVED 7:6
     * 00
     *
     * RESERVED 5:4
     * 00
     *
     * VOLUME
     * 1111 = loudest volume
     */
  
  /* register 0x06 */
  0b00000000, 
    /* 
     * RESERVED 15
     * 0
     *
     * OPEN_MODE open reserved registers mode
     * 00 = suggested default
     *
     * Bits 12:8 are not specified, so assume all 0's
     * 00000
     */ 
   
  0b00000000, 
    /* 
     *  Bits 7:0 are not specified, so assume all 0's
     *  00000000
     */
    
  /* register 0x07 */
  0b01000010, 
    /* 
     *  RESERVED 15 
     * 0
     *
     * TH_SOFRBLEND threshhold for noise soft blend setting
     * 10000 = using default value
     *
     * 65M_50M MODE 
     * 1 = only applies to BAND setting of 0b11, so could probably use 0 here too
     *
     * RESERVED 8
     * 0
     */    
  
  0b00000010, 
    /*   
     *  SEEK_TH_OLD seek threshold for old seek mode
     * 000000
     *
     * SOFTBLEND_EN soft blend enable
     * 1 = using default value
     *
     * FREQ_MODE
     * 0 = using defualt value
     */  
};

/* After reset, we can tune the device
 * We only need program the first 4 bytes in order to do this
 */
uint8_t tune_config[] = {
  /* register 0x02 */
  0b11100000, 
    /* 
     * DHIZ audio output high-z disable
     * 1 = normal operation
     *
     * DMUTE mute disable 
     * 1 = normal operation
     *
     * MONO mono select
     * 0 = stereo
     *
     * BASS bass boost
     * 0 = disabled
     *
     * RCLK NON-CALIBRATE MODE 
     * 0 = RCLK is always supplied
     *
     * RCLK DIRECT INPUT MODE 
     * 0 = ??? not certain what this does
     *
     * SEEKUP
     * 0 = seek in down direction
     *
     * SEEK
     * 0 = disable / stop seek (i.e. don't seek)
     */
    
   0b00000101, 
    /* 
     * SKMODE seek mode: 
     * 0 = wrap at upper or lower band limit and contiue seeking
     *
     * CLK_MODE clock mode
     * 000 = 32.768kHZ clock rate (match the watch cystal on the module) 
     *
     * RDS_EN radio data system enable
     * 0 = disable radio data system
     *
     * NEW_METHOD use new demodulate method for improved sensitivity
     * 0 = presumably disabled 
     *
     * SOFT_RESET
     * 0 = don't reset this time around
     *
     * ENABLE power up enable: 
     * 1 = enabled
     */ 

   /* register 0x03 */
   /* Here's where we set the frequency we want to tune to */
   (channel >> 2), 
    /* CHAN channel select 8 most significant bits of 10 in total   */

   ((channel & 0b11) << 6 ) | 0b00010000
    /* 
     *  CHAN two least significant bits of 10 in total 
     *
     * DIRECT MODE used only when test
     * 0 = presumably disabled
     *
     * TUNE commence tune operation 
     * 1 = enable (i.e. tune to selected channel)
     *
     * BAND band select
     * 00 = select the 87-108MHz band
     *
     * SPACE channel spacing
     * 00 = select spacing of 100kHz between channels
     */  
};


void setup()
{
 // Serial.begin(9600);
  
  /* Conect to RDA5807M FM Tuner: */
  Wire.begin(); /* join i2c bus (address optional for master) */
  
  Wire.beginTransmission(RDA5807M_ADDRESS); /* Sending boot configuration (device should reset) */
  Wire.write(boot_config, BOOT_CONFIG_LEN); /* Write the boot configuration bytes to the RDA5807M */
  Wire.endTransmission();
 
  Wire.beginTransmission(RDA5807M_ADDRESS); /* Tuning to channel */
  Wire.write(tune_config, TUNE_CONFIG_LEN); /* Write the tuning configuration bytes to the RDA5807M */
  Wire.endTransmission(); 
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);
  pinMode(swPin, INPUT); 
 pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  pinMode(dataPin, OUTPUT);
  digitalWrite(latchPin, LOW);
  for(int i=0;i<5;i++){ 
 shiftOut(dataPin, clockPin, MSBFIRST, 0b10111111);}
 digitalWrite(latchPin, HIGH);
}//setup end

void loop()
    
{
 if (flag1==0&&millis() - tmr1>500)  
     { 
        tmr1 = millis();
 myChangeChannel(channel);             
 output();
  flag1=1;}
  /* Read Rotary Encoder: */
  int change = getEncoderTurn();

  if (change > 0){
    channel++;
    myChangeChannel(channel);
    }
  else if(change < 0){
    channel--;
    myChangeChannel(channel);
    }
  if(channel > 210) 
  {
    channel = 210;
  }
  if(channel < 1) 
  {
    channel = 1;
  }
 
 frequency = channel+870;
 n1 = (frequency / 1000) % 10;
 n2 = (frequency / 100) % 10;
 n3 = (frequency / 10) % 10;
 n4 =  frequency % 10;

  switch (n1)
{
  case 0:
  case 2:
  case 3:
  case 4:
  case 5:
  case 6:
  case 7:
  case 8:
  case 9:
  a = 255;
  break;
  case 1:
  a = 249;
  break;
 
  
  }    

      switch (n2)
{
  case 0:
  b = 0b11000000;
  break;
  case 1:
  b = 249;
  break;
  case 2:
  b =164;
  break;
  case 3:
  b=176;
  break;
  case 4:
  b=153;
  break;
  case 5:
  b = 146;
  break;
  case 6:
  b =130;
  break;
  case 7:
  b = 248;
  break;
  case 8:
  b = 128;
  break;
  case 9:
  b =144;
  break;
  } 
    
    switch (n3)
{
  case 0:
  c = 0b01000000;
  break;
  case 1:
  c = 121;
  break;
  case 2:
  c = 36;
  break;
  case 3:
  c= 0b00110000;
  break;
  case 4:
  c=25;
  break;
  case 5:
  c = 18;
  break;
  case 6:
  c =02;
  break;
  case 7:
  c = 120;
  break;
  case 8:
  c = 0;
  break;
  case 9:
  c =16;
  break;
  } 
 
    switch (n4)
{
  case 0:
  d = 0b11000000;
  break;
  case 1:
  d = 249;
  break;
  case 2:
  d = 164;
  break;
  case 3:
  d = 0b10110000;
  break;
  case 4:
  d=153;
  break;
  case 5:
  d = 146;
  break;
  case 6:
  d =130;
  break;
  case 7:
  d = 248;
  break;
  case 8:
  d = 128;
  break;
  case 9:
  d = 144;
  break;
  }  
  if(change!=0){
 output();
  }//delay(100);
 
 if(digitalRead(swPin)==LOW){
  EEPROM.update(0,channel);}
  while(digitalRead(swPin)==LOW){
  digitalWrite(latchPin, LOW);
  for(int i=0;i<5;i++){ 
 shiftOut(dataPin, clockPin, MSBFIRST, 255);}
 digitalWrite(latchPin, HIGH);
 delay(100);
 output();
 delay(100);
  }         
 
  
}//loop end

/*
 * Function to read Rotary Encoder turn:
 * left or right
 * Returns: 1 or -1
 */
int getEncoderTurn(void)
{
  static int oldA = HIGH; // set the oldA as HIGH
  static int oldB = HIGH; // set the oldB as HIGH
  int result = 0;
  int newA = digitalRead(clkPin);   // read the value of clkPin to newA
  int newB = digitalRead(dtPin);    // read the value of dtPin to newB
  
 if (newA != oldA || newB != oldB) // if the value of clkPin or the dtPin has changed
  {
    /* something has changed */
    if (oldA == HIGH && newA == LOW)
    {
      result = (oldB * 2 - 1);
      /* Serial.print("Result: ");
         Serial.println(result); */
    }
  }
  oldA = newA;
  oldB = newB;
  
  return result; // 1 or -1
}


/*
 * Function to change channel on radio RDA5807
 * Example: channel = 191 
 */
void myChangeChannel(int channel){ /* void if nothing is returned else int */
  /*
   * first write new channel to tune_config massive
   */
   tune_config[2] = (channel >> 2); 
   tune_config[3] = ((channel & 0b11) << 6 ) | 0b00010000;
      
      Wire.begin();
      Wire.beginTransmission(RDA5807M_ADDRESS);
      Wire.write(tune_config, TUNE_CONFIG_LEN);
      Wire.endTransmission();

  }

void output()
{
  digitalWrite(latchPin, LOW); 
 shiftOut(dataPin, clockPin, MSBFIRST, d);
 shiftOut(dataPin, clockPin, MSBFIRST, c);
 shiftOut(dataPin, clockPin, MSBFIRST, b);
 shiftOut(dataPin, clockPin, MSBFIRST, a);
 digitalWrite(latchPin, HIGH);
}

Энкодер
http://forum.rcl-radio.ru/uploads/images/2023/11/bf0efea4670aee13c9a75bc0801ecb4a.jpg
схема дисплея
http://forum.rcl-radio.ru/uploads/images/2023/11/7bb4d23010c20fa803de539e39c9fd14.jpg
http://forum.rcl-radio.ru/uploads/images/2023/11/9e27bb84e1e91233cf3da007bcfb58f1.jpg
Примерная печатная плата
Данный контент доступен только зарегистрированным пользователям.

Плата ардуино NG or older. Чип Atmega8. Создаем прошивку: Скетч -Экспорт бинарного файла.В папке скетча будет прошивка.