PIC18F2520驱动RDA5807方案
**** Hidden Message *****是一个非常简单的固件,用于控制RDA5807 I2C 无线电 ic。
[*]2x16 LCD 显示屏。
[*]存储 6 个内存位置。
[*]RDS 就绪。
[*]音量控制。
/*
File: main.c
Copyright 2016 Marcos Mori de Siqueira <mori.br@gmail.com>
Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
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.
*/
//#include <p18cxxx.h>
#include <p18f2520.h>
#include <delays.h>
#include <usart.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <i2c.h>
#include <timers.h>
#include "rda5807.h"
#include "hardwareprofile.h"
#include "LCDBlocking.h"
#include "TimeDelay.h"
#include "keypad.h"
#include "log.h"
#include "eeprom.h"
#include "rds.h"
#include "options.h"
#include "test.h"
#include <math.h>
#pragma config OSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config MCLRE= ON
#pragma config PWRT = ON
#pragma config PBADEN = OFF
#define MAX_VOLUME 0x0C //0x0F
#define SAVE_TIMEOUT 5000
#define BACK2IDLE_TIMEOUT 1000
#define MENU_TIMEOUT 50000
#define STATE_IDLE 0
#define STATE_VOLUME 1
#define STATE_MEMORY 2
#define STATE_MENU 3
#define STATE_LAST_BASIC 3
#define STATE_LAST 4
static BYTE mem_idx = 0;
static BYTE state = STATE_IDLE;
static LONG state_timeout = 0;
extern volatile RDSINFO rds;
static RDAINFO info;
typedef struct
{
RDA_MEMORY mem;
LONG mem_save_timeout;
BYTE enabled;
} SAVEINFO;
static SAVEINFO save_info = {{0},0,0};
static void update_lcd(void);
static void process_dn(void);
static void process_up(void);
static BYTE setup_memory(void);
void main(void)
{
char *c = 0;
DWORD counter = 0, read = 0;
BYTEevt;
DWORD ellapsed = 0;
BYTEbtn_ok_pressed = 0;
CMCON = 0x07; // Comparators Off
CVRCON= 0; // voltage reference=off
ADCON1= 0x0F; // Disable ALL adc channels, PDF page 226
LED1_TRIS = OUTPUT_PIN;
I2C_SCL_TRIS = OUTPUT_PIN;
I2C_SDA_TRIS = OUTPUT_PIN;
// Uart
OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 10);
LOG((ROMCHAR)"\r\n-------------------------------------------------\r\n");
KeypadInit();
LCDInit();
// Setup I2C
OpenI2C(MASTER, SLEW_OFF);
//SSPADD = 0x32; //100kHz Baud clock @20MHz
SSPADD = 0x0B;//400kHz Baud clock @20MHz
LCDErase();
strcpypgm2ram(c, (ROMCHAR)" STARTING ");
LCDWriteLine(1, c);
memset(save_info.mem.data, 0, sizeof(RDA_MEMORY));
//TEST_eeprom_reset();
if(!EEPROM_load_data(&save_info.mem))
{
LOG((ROMCHAR)"loading default config\r\n");
save_info.mem.flags = RDA_FLAG_RDS|RDA_FLAG_BASS;
save_info.mem.channel = 101.7;
save_info.mem.volume= 1;
//save_info.mem.memory = 97.7;
//save_info.mem.memory = 103.3;
//save_info.mem.memory = 90.5;
}
LOG((ROMCHAR)"init\r\n");
RDA5807M_init();
RDA5807M_PowerON();
DelayMs(200);
// Setup radio
RDA5807M_SetVolume(save_info.mem.volume);
RDA5807M_SetFrequency(save_info.mem.channel);
RDA5807M_BassBoost(save_info.mem.flags & RDA_FLAG_BASS);
RDA5807M_Mono(save_info.mem.flags & RDA_FLAG_MONO);
RDA5807M_RDS(save_info.mem.flags & RDA_FLAG_RDS);
while(1)
{
LED1 = 0;
if(counter++ > 3000)
{
counter = 0;
LED1 = 1;
DelayMs(10);
}
evt = GetButtonsEvents();
if(evt != EVENT_NOTHING)
{
if(evt == EVENT_UP_BUTTON_PUSHED)
{
if(state != STATE_MENU)
{
//LOG((ROMCHAR)"up %d\r\n", state);
if(++state >= STATE_LAST_BASIC)
state = STATE_IDLE;
//LOG((ROMCHAR)"up %d\r\n", state);
if(state == STATE_MEMORY)
mem_idx = setup_memory();
if(state > STATE_IDLE)
state_timeout = BACK2IDLE_TIMEOUT;
else
{
state_timeout = 0;
rds.ps_valid = 1;
rds.rt_valid = 1;
}
}
else
{
state_timeout = MENU_TIMEOUT;
MENU_run(MENU_UP);
}
}
else if(evt == EVENT_DN_BUTTON_PUSHED)
{
if(state != STATE_MENU)
{
//LOG((ROMCHAR)"dn %d\r\n", state);
if(--state >= 0xFF)
state = STATE_IDLE;
//LOG((ROMCHAR)"dn %d\r\n", state);
if(state > STATE_IDLE)
state_timeout = BACK2IDLE_TIMEOUT;
else
{
state_timeout = 0;
rds.ps_valid = 1;
rds.rt_valid = 1;
}
}
else
{
state_timeout = MENU_TIMEOUT;
MENU_run(MENU_DOWN);
}
}
else if(evt == EVENT_LEFT_BUTTON_PUSHED)
{
//LOG((ROMCHAR)"left\r\n");
if(state == STATE_MENU)
{
state_timeout = MENU_TIMEOUT;
MENU_run(MENU_LEFT);
}
else
process_dn();
}
else if(evt == EVENT_RIGHT_BUTTON_PUSHED)
{
//LOG((ROMCHAR)"right\r\n");
if(state == STATE_MENU)
{
state_timeout = MENU_TIMEOUT;
MENU_run(MENU_RIGHT);
}
else
process_up();
}
else if(evt == EVENT_OK_BUTTON_PUSHED)
{
btn_ok_pressed = 1;
ellapsed = 0;
}
else if(evt == EVENT_MENU_BUTTON_PUSHED)
{
LOG((ROMCHAR)"menu\r\n");
if(state == STATE_MENU)
state_timeout = 1;// change to idle
else
{
MENU_init(&save_info.mem);
state = STATE_MENU;
state_timeout = MENU_TIMEOUT;
}
}
else if(evt == EVENT_OK_BUTTON_RELEASED)
{
LOG((ROMCHAR)"OK released\r\n");
btn_ok_pressed = 0;
if(ellapsed < 250)
{
if(state == STATE_MENU)
{
if(MENU_run(MENU_OK))
{
save_info.enabled = 1;
state_timeout = 400;
}
else
state_timeout = MENU_TIMEOUT;
}
else
{
switch(state)
{
case STATE_IDLE:
RDA5807M_Mute();
break;
case STATE_MEMORY:
if(save_info.mem.memory > 0)
{
RDA5807M_SetFrequency(save_info.mem.memory);
state_timeout = 1;// change to idle
}
break;
}
}
}
}
}
if(read++ > 1)
{
read = 0;
RDA5807M_Read(&info);
update_lcd();
}
if(save_info.mem_save_timeout > 0)
{
if(--save_info.mem_save_timeout <= 0)
{
save_info.mem_save_timeout = 0;
LOG((ROMCHAR)"SAVE DATA EEPROM\r\n");
LOG((ROMCHAR)"chann %d\r\n", (int)save_info.mem.channel);
EEPROM_save_data(&save_info.mem);
}
}
// Dont back to IDLE while pressing memory saving button
if(!btn_ok_pressed && state_timeout > 0)
{
if(--state_timeout <= 0)
{
LOG((ROMCHAR)"IDLE\r\n");
state_timeout = 0;
rds.ps_valid = 1;
rds.rt_valid = 1;
state = STATE_IDLE;
}
}
ellapsed++;
if(btn_ok_pressed && ellapsed > 250)
{
save_info.mem.memory = save_info.mem.channel;
state_timeout = 1;
}
}
}
static void process_up(void)
{
switch(state)
{
case STATE_IDLE:
save_info.enabled = 1;
RDA5807M_SeekUp();
break;
case STATE_VOLUME:
if(++save_info.mem.volume >= MAX_VOLUME)
save_info.mem.volume = MAX_VOLUME;
state_timeout = BACK2IDLE_TIMEOUT;
RDA5807M_SetVolume(save_info.mem.volume);
break;
case STATE_MEMORY:
if(++mem_idx >= MAX_CHANNEL_MEM)
mem_idx = MAX_CHANNEL_MEM-1;
state_timeout = BACK2IDLE_TIMEOUT;
break;
}
}
static void process_dn(void)
{
switch(state)
{
case STATE_IDLE:
save_info.enabled = 1;
RDA5807M_SeekDown();
break;
case STATE_VOLUME:
if(--save_info.mem.volume >= 0xFF)
save_info.mem.volume = 0;
state_timeout = BACK2IDLE_TIMEOUT;
RDA5807M_SetVolume(save_info.mem.volume);
break;
case STATE_MEMORY:
if(--mem_idx >= 0xFF)
mem_idx = 0;
state_timeout = BACK2IDLE_TIMEOUT;
break;
}
}
static void update_volume(void)
{
BYTE i = 0;
strcpypgm2ram(LCDText, (ROMCHAR)"VOL ");
for(; i < save_info.mem.volume; ++i)
strcatpgm2ram(LCDText, (ROMCHAR)"\xFF");
}
static BYTE setup_memory(void)
{
BYTE i = 0;
for(; i < MAX_CHANNEL_MEM; ++i)
{
if(save_info.mem.memory > 0 && save_info.mem.memory == info.freq)
{
return i;
}
}
return 0xFF;
}
static void update_lcd(void)
{
int num, dec;
char c = {0};
BYTE memidx = 0;
char m = {' '};
char m1 = {' ',' ', 0};
static BYTE size = 0;
static BYTE pos= 0;
static WORD ps = 0;
if(state < STATE_LAST_BASIC)
{
// Draw line 1
if(state == STATE_MEMORY)
{
// Display current memory station
strncpypgm2ram(LCDText, (ROMCHAR)" FM ---.- ", 16);
if(save_info.mem.memory > 0)
{
num = save_info.mem.memory;
dec = (int)floor(((save_info.mem.memory - num) * 100)/10);
if(dec % 2 == 0) dec += 1;
sprintf(c, (ROMCHAR)" FM %3d.%1d ", num, dec);
strncpy(LCDText, c, 16);
}
}
else
{
// Display station currently tunned
strncpypgm2ram(LCDText, (ROMCHAR)" \xA5\xA5 SCANNING \xA5\xA5 ", 16);
//if(info.fmtrue && info.tuneok)
//{
num = info.freq;
dec = (int)floor(((info.freq - num) * 100)/10);
if(dec % 2 == 0) dec += 1;
memidx = setup_memory();
if(memidx != 0xFF) {
itoa(memidx+1, m);
m1 = 'M';
m1 = m;
}
if(info.stereo)
sprintf(c, (ROMCHAR)"%1d %s FM %3d.%1d\xA5", info.rssi, m1, num, dec);
else
sprintf(c, (ROMCHAR)"%1d %s FM %3d.%1d ", info.rssi, m1, num, dec);
strncpy(LCDText, c, 16);
if(info.fmtrue && info.tuneok)
{
// Start save timer
if(save_info.enabled)
{
save_info.mem.channel = info.freq;
save_info.mem_save_timeout = SAVE_TIMEOUT;
save_info.enabled = 0;
}
}
}
switch(state)
{
case STATE_IDLE:
{
if(!rds.use_rt && rds.ps_valid)
{
rds.ps_valid = 0;
memset(LCDText, ' ', 16);
strncpy(&LCDText, rds.ps_copy, 8);
}
else
{
if(rds.rt_valid)
{
rds.rt_valid = 0;
memset(LCDText, ' ', 16);
size = strlen(rds.rt_copy);
pos = 0;
ps = 0;
strncpy(LCDText, rds.rt_copy, size > 16 ? 16 : size);
}
else
{
if(rds.use_rt && ps++ > 30)
{
ps = 0;
if(size < 16)
strncpy(LCDText, rds.rt_copy, size > 16 ? 16 : size);
else
strncpy(LCDText, &rds.rt_copy, (size - pos) > 16 ? 16 : size);
}
}
}
}
break;
case STATE_VOLUME:
update_volume();
break;
case STATE_MEMORY:
{
switch(mem_idx)
{
case 0:
strncpypgm2ram(LCDText, (ROMCHAR)"MEM \x0A51 2 3 4 5 6", 16);
break;
case 1:
strncpypgm2ram(LCDText, (ROMCHAR)"MEM 1 \x0A52 3 4 5 6", 16);
break;
case 2:
strncpypgm2ram(LCDText, (ROMCHAR)"MEM 1 2 \x0A53 4 5 6", 16);
break;
case 3:
strncpypgm2ram(LCDText, (ROMCHAR)"MEM 1 2 3 \x0A54 5 6", 16);
break;
case 4:
strncpypgm2ram(LCDText, (ROMCHAR)"MEM 1 2 3 4 \x0A55 6", 16);
break;
case 5:
strncpypgm2ram(LCDText, (ROMCHAR)"MEM 1 2 3 4 5 \x0A56", 16);
break;
default:
LOG((ROMCHAR)"ERR %d\r\n", mem_idx);
mem_idx = 0;
break;
}
}
break;
}
}
else
{
MENU_draw();
}
LCDUpdate();
}
只要实现I2C读写一般就没太多问题了。所以学会I2C很重要啊。 {:victory:}
页:
[1]