[资料分享] msp430g2452数字收音机数码管显示

fish001   2018-9-22 20:37 楼主
手上有个收音机模块,借鉴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();
  }
}


回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复