手上有个收音机模块,借鉴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
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();
}
}