AD9850驱动程序--MSP430版本
前段时间忙着画板子搞运放搞滤波了,程序更新的少,发现MSP430不是太好用,尤其Timer,不过也与我使用内部晶振有关,产生正玄波之前用MSP430发出PWM,再进行滤波变为正弦波太麻烦了,这次改用DDS芯片,今天板子回来一会就调了出来很方便。
AD9850为一款DDS芯片,这里不做什么详细介绍了,有两种接口:serial 和 parrel,两种接口驱动均完成
1 /* 2 * AD9850.h 3 * 4 * Created on: 2013-7-12 5 * Author: Allen 6 */ 7 8 #ifndef AD9850_H_ 9 #define AD9850_H_ 10 11 #include <MSP430G2553.h> 12 #include "MyType.h" 13 14 15 //---------------------------------------------------------------------------------- 16 //AD9850:W_CLK P2.5 17 #define AD9850_W_CLK_DIR (P2DIR) 18 #define AD9850_W_CLK_OUT (P2OUT) 19 #define AD9850_W_CLK_PIN_NUM (BIT5) 20 21 #define AD9850_W_CLK_IO_INIT (Set_Bit(P2DIR,AD9850_W_CLK_PIN_NUM)) 22 #define AD9850_W_CLK_H (Set_Bit(P2OUT,AD9850_W_CLK_PIN_NUM)) 23 #define AD9850_W_CLK_L (Clr_Bit(P2OUT,AD9850_W_CLK_PIN_NUM)) 24 25 //---------------------------------------------------------------------------------- 26 //AD9850:FQ_UP P2.4 27 #define AD9850_FQ_UP_DIR (P2DIR) 28 #define AD9850_FQ_UP_OUT (P2OUT) 29 #define AD9850_FQ_UP_PIN_NUM (BIT4) 30 31 #define AD9850_FQ_UP_IO_INIT (Set_Bit(P2DIR,AD9850_FQ_UP_PIN_NUM)) 32 #define AD9850_FQ_UP_H (Set_Bit(P2OUT,AD9850_FQ_UP_PIN_NUM)) 33 #define AD9850_FQ_UP_L (Clr_Bit(P2OUT,AD9850_FQ_UP_PIN_NUM)) 34 35 //---------------------------------------------------------------------------------- 36 //AD9850:RESET P2.3 37 #define AD9850_RESET_DIR (P2DIR) 38 #define AD9850_RESET_OUT (P2OUT) 39 #define AD9850_RESET_PIN_NUM (BIT3) 40 41 #define AD9850_RESET_IO_INIT (Set_Bit(P2DIR,AD9850_RESET_PIN_NUM)) 42 #define AD9850_RESET_H (Set_Bit(P2OUT,AD9850_RESET_PIN_NUM)) 43 #define AD9850_RESET_L (Clr_Bit(P2OUT,AD9850_RESET_PIN_NUM)) 44 45 //---------------------------------------------------------------------------------- 46 //AD9850:BIT_DATA P1.7 47 #define AD9850_BIT_DATA_DIR (P1DIR) 48 #define AD9850_BIT_DATA_OUT (P1OUT) 49 #define AD9850_BIT_DATA_PIN_NUM (BIT7) 50 51 #define AD9850_BIT_DATA_IO_INIT (Set_Bit(P1DIR,AD9850_BIT_DATA_PIN_NUM)) 52 #define AD9850_BIT_DATA_H (Set_Bit(P1OUT,AD9850_BIT_DATA_PIN_NUM)) 53 #define AD9850_BIT_DATA_L (Clr_Bit(P1OUT,AD9850_BIT_DATA_PIN_NUM)) 54 55 56 extern void AD9850_INIT_SERIAL(void); 57 58 extern void AD9850_RESET_SERIAL(void); 59 60 extern void AD9850_WR_SERIAL(unsigned char w0,double frequence); 61 62 extern void AD9850_INIT_PARREL(void); 63 64 extern void AD9850_RESET_PARREL(void); 65 66 extern void AD9850_WR_PARREL(unsigned char w0,double frequence); 67 68 69 #endif /* LED_H_ */
以上是头文件完成了pin定义与位操作,并口的数据线操作并没定义,到时候直接用port操作很方便,AD9850的D0-D7与MSP430的P1.0-P1.7对应,一次写入8位很简单。
其中使用了#include "MyType.h"中一些操作:
// C
#define Set_Bit(val, bitn) (val |= (/*1 <<*/(bitn)))
#define Clr_Bit(val, bitn) (val &= ~(/*1<<*/(bitn)))
#define Get_Bit(val, bitn) (val & (1<<(bitn)) )
先写的串口的程序:
1 void AD9850_INIT_SERIAL(void) 2 { 3 AD9850_W_CLK_IO_INIT; 4 AD9850_FQ_UP_IO_INIT; 5 AD9850_RESET_IO_INIT; 6 AD9850_BIT_DATA_IO_INIT; 7 }
1 void AD9850_RESET_SERIAL(void) 2 { 3 AD9850_W_CLK_L; 4 AD9850_FQ_UP_L; 5 //rest信号 6 AD9850_RESET_L; 7 AD9850_RESET_H; 8 AD9850_RESET_L; 9 //w_clk信号 10 AD9850_W_CLK_L; 11 AD9850_W_CLK_H; 12 AD9850_W_CLK_L; 13 //fq_up信号 14 AD9850_FQ_UP_L; 15 AD9850_FQ_UP_H; 16 AD9850_FQ_UP_L; 17 18 }
1 void AD9850_WR_SERIAL(unsigned char w0,double frequence) 2 { 3 unsigned char i,w; 4 long int y; 5 double x; 6 //计算频率的HEX值 7 x=4294967295/20;//适合125M晶振 8 //如果时钟频率不为20MHZ,修改该处的频率值,单位MHz !!! 9 frequence=frequence/1000000; 10 frequence=frequence*x; 11 y=frequence; 12 //写w4数据 13 w=(y>>=0); 14 for(i=0;i<8;i++) 15 { 16 // ad9850_bit_data=(w>>i)&0x01; 17 if((w>>i)&0x01) 18 AD9850_BIT_DATA_H; 19 else 20 AD9850_BIT_DATA_L; 21 AD9850_W_CLK_H; 22 AD9850_W_CLK_L; 23 } 24 //写w3数据 25 w=(y>>8); 26 for(i=0;i<8;i++) 27 { 28 if((w>>i)&0x01) 29 AD9850_BIT_DATA_H; 30 else 31 AD9850_BIT_DATA_L; 32 AD9850_W_CLK_H; 33 AD9850_W_CLK_L; 34 } 35 //写w2数据 36 w=(y>>16); 37 for(i=0;i<8;i++) 38 { 39 if((w>>i)&0x01) 40 AD9850_BIT_DATA_H; 41 else 42 AD9850_BIT_DATA_L; 43 AD9850_W_CLK_H; 44 AD9850_W_CLK_L; 45 } 46 //写w1数据 47 w=(y>>24); 48 for(i=0;i<8;i++) 49 { 50 if((w>>i)&0x01) 51 AD9850_BIT_DATA_H; 52 else 53 AD9850_BIT_DATA_L; 54 AD9850_W_CLK_H; 55 AD9850_W_CLK_L; 56 } 57 //写w0数据 58 w=w0; 59 for(i=0;i<8;i++) 60 { 61 if((w>>i)&0x01) 62 AD9850_BIT_DATA_H; 63 else 64 AD9850_BIT_DATA_L; 65 AD9850_W_CLK_H; 66 AD9850_W_CLK_L; 67 } 68 //移入始能 69 AD9850_FQ_UP_H; 70 AD9850_FQ_UP_L; 71 72 }
串行连接时候需要注意pin2-4的连接:
以下是并行部分程序:
1 void AD9850_INIT_PARREL(void) 2 { 3 AD9850_W_CLK_IO_INIT; 4 AD9850_FQ_UP_IO_INIT; 5 AD9850_RESET_IO_INIT; 6 P1DIR=0xff; 7 8 }
1 void AD9850_RESET_PARREL(void) 2 { 3 AD9850_W_CLK_L; 4 AD9850_FQ_UP_L; 5 //rest信号 6 AD9850_RESET_L; 7 AD9850_RESET_H; 8 AD9850_RESET_L; 9 }
1 void AD9850_WR_PARREL(unsigned char w0,double frequence) 2 { 3 unsigned char w; 4 long int y; 5 double x; 6 //计算频率的HEX值 7 x=4294967295/20;//适合20M晶振 8 //如果时钟频率不为20MHZ,修改该处的频率值,单位MHz !!! 9 frequence=frequence/1000000; 10 frequence=frequence*x; 11 y=frequence; 12 //写w0数据 13 w=w0; 14 P1OUT=w; //w0 15 AD9850_W_CLK_H; 16 AD9850_W_CLK_L; 17 //写w1数据 18 w=(y>>24); 19 P1OUT=w; //w1 20 AD9850_W_CLK_H; 21 AD9850_W_CLK_L; 22 //写w2数据 23 w=(y>>16); 24 P1OUT=w; //w2 25 AD9850_W_CLK_H; 26 AD9850_W_CLK_L; 27 //写w3数据 28 w=(y>>8); 29 P1OUT=w; //w3 30 AD9850_W_CLK_H; 31 AD9850_W_CLK_L; 32 //写w4数据 33 w=(y>>0); 34 P1OUT=w; //w4 35 AD9850_W_CLK_H; 36 AD9850_W_CLK_L; 37 //移入始能 38 AD9850_FQ_UP_H; 39 AD9850_FQ_UP_L; 40 41 }
主函数:
1 char mode=0; //0:serial 1:parrel 2 /* 3 * main.c 4 */ 5 int main(void) { 6 WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer 7 8 mode=0; 9 10 if(mode==0) 11 { 12 13 AD9850_INIT_SERIAL(); 14 AD9850_RESET_SERIAL(); 15 AD9850_WR_SERIAL(0,18000); 16 } 17 else if(mode==1) 18 { 19 20 AD9850_INIT_PARREL(); 21 AD9850_RESET_PARREL(); 22 AD9850_WR_PARREL(0,25000); 23 24 } 25 26 27 28 29 30 while(1) 31 { 32 33 34 } 35 return 0; 36 }
个人感受:方便,简单嘿嘿