|
手上有個收音機模塊,借鑒51單片機例程,自己430寫了個小程序。用數碼管顯示。
剛寫好了,又被刷沒有了,我哭了,還得再寫,這太啃了吧。
言歸正傳,這個小實驗也是我無意中想的,手中有430的片子,又想自己做個小東西,只要能個簡單的電子收音機,程序代碼都是借鑒的,所以這個只是玩玩而已,以供參考。
//iic.h 這個是收音機的驅動程序,我是借鑒新浪一位網友c51程序寫得,大家搜下就知道了。
#include"config.h"
uchar fm_write[5]={0x00,0x00,0x31,0x17,0x00};
uchar fm_read[5]={0,0,0,0,0};
uint freq,PLL,frequency;
uchar count;
uchar mode,hisi;
//msp430內部PLL時鐘12M,最大可以達到16M.
void extern_16m()
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_12MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_12MHZ;
DCOCTL = CALDCO_12MHZ; // Load 8MHz constants
frequency=10585;
}
void iic_start()
{
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA1; //發送起始條件的數據信號
delay_us(1);
SCL1;
delay_us(5); //起始條件建立時間大于4.7us,延時
SDA0; //發送起始信號
delay_us(5); // 起始條件鎖定時間大于4μs
SCL0; //鉗住I2C總線,準備發送或接收數據
// delay_us(2);
}
void iic_stop()//總線結束
{
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA0; //發送結束條件的數據信號
delay_us(1); //發送結束條件的時鐘信號
SCL1; //結束條件建立時間大于4us
delay_us(5);
SDA1; //發送I2C總線結束信號
delay_us(1);
}
void write_8bit(uchar c)
{
uchar BitCnt;
SDA_DIR_OUT;
SCL_DIR_OUT;
for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的數據長度為8位
{
if(c&0x80)
SDA1; //判斷發送位
else
SDA0;
delay_us(1);
SCL1;
delay_us(5);
c=c<<1;
SCL0; //置時鐘線為高,通知被控器開始接收數據位
delay_us(1);
}
}
uchar read_8bit()//讀取8bit數據
{
SCL_DIR_OUT;
SDA_DIR_IN;
uchar i,dat=0;
for(i=0;i<8;i++)
{ SCL1;
dat<<=1;
if(SDA_IN==0x40)
dat|=0x01;
delay_us(5);
SCL0;
}
return(dat);
}
void send_ack()//發送認可位,用于讀取數據的認可
{ SDA_DIR_OUT;
SCL_DIR_OUT;
SDA0;
delay_us(1);
SCL1;
delay_us(5);
SCL0;
}
void send_noack()
{
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA1;
delay_us(1);
SCL1;
delay_us(5);
SDA0;
SCL0;
}
uchar check_ack()//檢測確認位,如果返回值是0表示數據傳輸成功
{ uchar ack_bit;
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA1;
delay_us(1);
SCL1;
delay_us(5);
SDA_DIR_IN;
ack_bit=SDA_IN;
SCL0;
return(ack_bit);
}
void get_frequency()
{ ulong y;
y=PLL;
hisi=fm_write[2]&0x10;
if(hisi)
freq=(y*8192+225000)/10000;
else
freq=(y*8192-225000)/10000 ;
}
void get_pll()
{ ulong freq1,y=frequency;
freq1=y*10000;
hisi=fm_write[2]&0x10;
if(hisi)
PLL=((freq1+225000)*4)/32768;
else
PLL=((freq1-225000)*4)/32768;
}
void read_5byte()
{uchar i,tempH,tempL;
iic_start();
write_8bit(read_order);
check_ack();
for(i=0;i<5;i++)
{fm_read[i]=read_8bit();
send_ack();
}
send_noack();
iic_stop();
tempH=fm_read[0];
tempL=fm_read[1];
tempH&=0x3f;
PLL=tempH*256+tempL;
get_frequency();
}
void write_5byte()
{uchar i;
iic_start();
write_8bit(write_order);
check_ack();
for(i=0;i<5;i++)
{write_8bit(fm_write[i]);
check_ack();
}
iic_stop();
}
void refurbish_5767()//FM收音芯片數據刷新一次
{
get_pll();//計算PLL,
fm_write[0]=PLL/256;
fm_write[1]=PLL%256;
fm_write[2]=0x31;
fm_write[3]=0x11;
fm_write[4]=0x00;
if(mode)fm_write[2]|=0x80;//給SUD=1,向上搜索模式
else fm_write[2]&=0x7f;//給SUD=0,向下搜索模式
write_5byte();
read_5byte();
}
//config.h
#include "io430.h"
#define CPU_F ((double)12000000) //外部高頻晶振8MHZ
//#define CPU_F ((double)32768) //外部低頻晶振32.768KHZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define SDA_DIR_OUT P1DIR|=BIT6
#define SDA_DIR_IN P1DIR&=~BIT6
#define SCL_DIR_OUT P1DIR|=BIT7
#define SDA_IN P1IN&BIT6
#define SDA1 P1OUT|=BIT6
#define SDA0 P1OUT&=~BIT6
#define SCL1 P1OUT|=BIT7
#define SCL0 P1OUT&=~BIT7
#define max_freq 12800
#define min_freq 7600
#define write_order 0xc0
#define read_order 0xc1
#define keycode P1IN&0x03
//key.h
#include "io430.h"
uchar key_value;
uchar key_code;
void key_init()
{
P1IE |= BIT0+BIT1+BIT2; // P1.0-P1.2 IO口中斷使能
P1IES |= 0x07; // P1.0-P1.2 IO口邊沿觸發中斷方式設置
P1IFG &= ~(BIT0+BIT1+BIT2); // P1.0-P1.2 IO口中斷標志位清除
}
//外部中斷查詢方式,如果有中斷就運行程序
void key_set()
{
if(key_value!=0)
{
switch(key_value)
{
case 0x01:
switch(mode)
{
case 0:mode=1;break;
case 1:mode=0;break;
default:mode=0;break;
}
break;
case 0x02:
switch(mode)
{
case 0:++frequency;break;
case 1:--frequency;break;
default:break;
}
break;
case 0x03:
switch(mode)
{
case 0:frequency+=10;break;
case 1:frequency-=10;break;
default:break;
}
break;
default:break;
}
if(frequency>max_freq)
frequency=min_freq;
if(frequency frequency=max_freq;
key_code=3*mode+key_value;
key_value=0;
}
}
//外部中斷判斷按鍵
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
switch (P1IFG&0x07)
{
case 0x01: key_value=0x01;
break;
case 0x02: key_value=0x02;
break;
case 0x04: key_value=0x03;
break;
default: P1IFG = 0; key_value=0; // P2.0-P2.2 IO口中斷標志位清除
break;
}
P1IFG = 0; // P2.0-P2.2 IO口中斷標志位清除
}
//ta.h
#include"config.h"
uint t;
uchar set_hex;
extern void display();
void init_TA()
{
TACCTL0 = CCIE; // TACCR0 interrupt enabled
TACCR0 = 60000; //5ms中斷一次
TACTL = TASSEL_2 + MC_1; // SMCLK, upmode
}
//顯示在數碼管上,我用的是cd4511,占用6的io口顯示數碼管,p2.0-p2.1位選,p2.2-p2.5段選。
void display()
{
P1OUT|=BIT3;
P2OUT=0X00;
switch(set_hex)
{
case 0:set_hex=1;P2OUT|=BIT0;P2OUT|=key_code<<2;break;
case 1:set_hex=0;P2OUT|=BIT1;P2OUT|=mode<<2;break;
default:break;
}
P1OUT&=-BIT3;
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
display();
if(++t==50)
{
t=0; //每250ms刷新數據
refurbish_5767();//FM收音芯片數據刷新一次
}
}
//main.c
#include"iic.h"
#include"key.h"
#include"config.h"
#include"ta.h"
#include"shumaguan.h"
int main( void )
{
extern_16m();
key_init();
init_TA();
shumaguan_init();
__bis_SR_register(GIE);
while(1)
{
key_set();
}
}
//iic.h
#include"config.h"
uchar fm_write[5]={0x00,0x00,0x31,0x17,0x00};
uchar fm_read[5]={0,0,0,0,0};
uint freq,PLL,frequency;
uchar count;
uchar mode,hisi;
void extern_16m()
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_12MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_12MHZ;
DCOCTL = CALDCO_12MHZ; // Load 8MHz constants
frequency=10585;
}
void iic_start()
{
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA1; //發送起始條件的數據信號
delay_us(1);
SCL1;
delay_us(5); //起始條件建立時間大于4.7us,延時
SDA0; //發送起始信號
delay_us(5); // 起始條件鎖定時間大于4μs
SCL0; //鉗住I2C總線,準備發送或接收數據
// delay_us(2);
}
void iic_stop()//總線結束
{
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA0; //發送結束條件的數據信號
delay_us(1); //發送結束條件的時鐘信號
SCL1; //結束條件建立時間大于4us
delay_us(5);
SDA1; //發送I2C總線結束信號
delay_us(1);
}
void write_8bit(uchar c)
{
uchar BitCnt;
SDA_DIR_OUT;
SCL_DIR_OUT;
for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的數據長度為8位
{
if(c&0x80)
SDA1; //判斷發送位
else
SDA0;
delay_us(1);
SCL1;
delay_us(5);
c=c<<1;
SCL0; //置時鐘線為高,通知被控器開始接收數據位
delay_us(1);
}
}
uchar read_8bit()//讀取8bit數據
{
SCL_DIR_OUT;
SDA_DIR_IN;
uchar i,dat=0;
for(i=0;i<8;i++)
{ SCL1;
dat<<=1;
if(SDA_IN==0x40)
dat|=0x01;
delay_us(5);
SCL0;
}
return(dat);
}
void send_ack()//發送認可位,用于讀取數據的認可
{ SDA_DIR_OUT;
SCL_DIR_OUT;
SDA0;
delay_us(1);
SCL1;
delay_us(5);
SCL0;
}
void send_noack()
{
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA1;
delay_us(1);
SCL1;
delay_us(5);
SDA0;
SCL0;
}
uchar check_ack()//檢測確認位,如果返回值是0表示數據傳輸成功
{ uchar ack_bit;
SDA_DIR_OUT;
SCL_DIR_OUT;
SDA1;
delay_us(1);
SCL1;
delay_us(5);
SDA_DIR_IN;
ack_bit=SDA_IN;
SCL0;
return(ack_bit);
}
void get_frequency()
{ ulong y;
y=PLL;
hisi=fm_write[2]&0x10;
if(hisi)
freq=(y*8192+225000)/10000;
else
freq=(y*8192-225000)/10000 ;
}
void get_pll()
{ ulong freq1,y=frequency;
freq1=y*10000;
hisi=fm_write[2]&0x10;
if(hisi)
PLL=((freq1+225000)*4)/32768;
else
PLL=((freq1-225000)*4)/32768;
}
void read_5byte()
{uchar i,tempH,tempL;
iic_start();
write_8bit(read_order);
check_ack();
for(i=0;i<5;i++)
{fm_read[i]=read_8bit();
send_ack();
}
send_noack();
iic_stop();
tempH=fm_read[0];
tempL=fm_read[1];
tempH&=0x3f;
PLL=tempH*256+tempL;
get_frequency();
}
void write_5byte()
{uchar i;
iic_start();
write_8bit(write_order);
check_ack();
for(i=0;i<5;i++)
{write_8bit(fm_write[i]);
check_ack();
}
iic_stop();
}
void refurbish_5767()//FM收音芯片數據刷新一次
{
get_pll();//計算PLL,
fm_write[0]=PLL/256;
fm_write[1]=PLL%256;
fm_write[2]=0x31;
fm_write[3]=0x11;
fm_write[4]=0x00;
if(mode)fm_write[2]|=0x80;//給SUD=1,向上搜索模式
else fm_write[2]&=0x7f;//給SUD=0,向下搜索模式
write_5byte();
read_5byte();
}
//config.h
#include "io430.h"
#define CPU_F ((double)12000000) //外部高頻晶振8MHZ
//#define CPU_F ((double)32768) //外部低頻晶振32.768KHZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define SDA_DIR_OUT P1DIR|=BIT6
#define SDA_DIR_IN P1DIR&=~BIT6
#define SCL_DIR_OUT P1DIR|=BIT7
#define SDA_IN P1IN&BIT6
#define SDA1 P1OUT|=BIT6
#define SDA0 P1OUT&=~BIT6
#define SCL1 P1OUT|=BIT7
#define SCL0 P1OUT&=~BIT7
#define max_freq 12800
#define min_freq 7600
#define write_order 0xc0
#define read_order 0xc1
#define keycode P1IN&0x03
//key.h
#include "io430.h"
uchar key_value;
uchar key_code;
void key_init()
{
P1IE |= BIT0+BIT1+BIT2; // P2.0-P2.2 IO口中斷使能
P1IES |= 0x07; // P2.0-P2.2 IO口邊沿觸發中斷方式設置
P1IFG &= ~(BIT0+BIT1+BIT2); // P2.0-P2.2 IO口中斷標志位清除
}
void key_set()
{
if(key_value!=0)
{
switch(key_value)
{
case 0x01:
switch(mode)
{
case 0:mode=1;break;
case 1:mode=0;break;
default:mode=0;break;
}
break;
case 0x02:
switch(mode)
{
case 0:++frequency;break;
case 1:--frequency;break;
default:break;
}
break;
case 0x03:
switch(mode)
{
case 0:frequency+=10;break;
case 1:frequency-=10;break;
default:break;
}
break;
default:break;
}
if(frequency>max_freq)
frequency=min_freq;
if(frequency<min_freq)
frequency=max_freq;
key_code=3*mode+key_value;
key_value=0;
}
}
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
switch (P1IFG&0x07)
{
case 0x01: key_value=0x01;
break;
case 0x02: key_value=0x02;
break;
case 0x04: key_value=0x03;
break;
default: P1IFG = 0; key_value=0; // P2.0-P2.2 IO口中斷標志位清除
break;
}
P1IFG = 0; // P2.0-P2.2 IO口中斷標志位清除
}
//ta.h
#include"config.h"
uint t;
uchar set_hex;
extern void display();
void init_TA()
{
TACCTL0 = CCIE; // TACCR0 interrupt enabled
TACCR0 = 60000; //5ms中斷一次
TACTL = TASSEL_2 + MC_1; // SMCLK, upmode
}
void display()
{
P1OUT|=BIT3;
P2OUT=0X00;
switch(set_hex)
{
case 0:set_hex=1;P2OUT|=BIT0;P2OUT|=key_code<<2;break;
case 1:set_hex=0;P2OUT|=BIT1;P2OUT|=mode<<2;break;
default:break;
}
P1OUT&=-BIT3;
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
display();
if(++t==50)
{
t=0;
refurbish_5767();//FM收音芯片數據刷新一次
}
}
//main.c
#include"iic.h"
#include"key.h"
#include"config.h"
#include"ta.h"
#include"shumaguan.h"
int main( void )
{
extern_16m();
key_init();
init_TA();
shumaguan_init();
__bis_SR_register(GIE);
while(1)
{
key_set();
}
}
|
-
-
收音機.zip
2016-3-30 19:47 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
203.25 KB, 下載次數: 144, 下載積分: 黑幣 -5
|