datasheet

基于MSP430的FSK 调制与解调制技术

2016-10-10来源: eefocus关键字:MSP430  FSK  调制  解调制技术
首先,讲讲什么是FSK?FSK(Frequency -Shift keying)中文你翻译过来就是頻移键控,它是利用载波的频率变化来传递数字信息。
FSK可以将频率信息转换成数字信息,这个叫做FSK的解调制;而将数字信息转换成频率信息,就叫做FSK的调制。那么FSK能干嘛?FSK有一个很“酷”功能——可以与音频口通讯。无论是安卓系统的手机还是iOS系统的手机,统统可以通过FSK调制与解调制技术实现与手机的数据通讯。安卓系统还好,还可以通过USB口直接通讯,而苹果的iOS却没有开发USB协议,如果想与iphone等苹果产品直接进行数据通讯,除了花大量时间与金钱去做MFI认证,那也只能通过音频了。前阵子很火的“卡拉卡”,就是走的这种方案。
下面就开始讲讲FSK的调制与解调制技术。数据传输可以是同步传输,也可以是异步传输。对于点对点的连接,异步传输通常有一个起始位和一个停止位。下图中可以看到:ASCII码‘K’(0x4B)二进制数字信息在频率信息表示。
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
可以看到 二进制信息‘0’在频率中用f1表示,二进制信息‘1’在频率中用f2表示。所以要实现FSK信息调制,只要将二进制信息'1'在1bit长度周期内生成f1的频率,二进制'0'在1bit长度周期内生成f2的频率;而FSK接调制,则判断频率是f1还是f2就可以判断是二进制'0'还是二进制'1'。
下面讲讲基于MSP430实现的FSK调制与解调制的思路。
1  FSK 调制
将串口0(USART0)作为用户应用软件与调制解调器之间的接口。我们配置串口0为异步传输,波特率为300bit/s。当数据写入串口缓冲区U0TXBUF,串口就开始在串口0发送引脚上输出相应的比特流(包括1位起始位,1位停止位,8为数据位, LSb形式发送)。可以看看MSP430的FSK调制模块:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
  串口0输出引脚直接外接到P1.3引脚。定时器A的捕获/比较模块CCR2配置成比较模式。定时器A配置成Timer_A.CLK频率下的定时任务。通过定时器A的定时与捕获/比较模块CCR2之间的相互配合,来触发生成相应频率的PWM信号,并在P1.7引脚输出。PWM的半周期可以通过下面公式计算:基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
  引脚P1.3配置成中断输入。当P1.3收到串口0发送的信号,就进入P1.3引脚的中断程序服务程序。中断程序的流程图如下:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
通过读取P1.3的中断触发边沿选择位P1IES3,中断服务程序就可以判断是下降沿触发还是上升沿触发引起的进入中断。如果是上升沿触发引起进入中断,则说明P1.3接收到的信号是'1',否则P1.3接收到的信号是'0'。因此,当P1.3检测到下降沿时,则在引脚P1.7输出信号‘0’对应的频率f1的PWM信号;当P1.3检测到上升沿,则在引脚P1.7输出信号'1'所对应的频率f2的PWM信号。转换结果如下图所示:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
在MSP430的具体实现代码:

#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR(void) {
if(UART_COM_PORT_IFG & MODULATOR_DIGITAL_IN) { // isr caused by MODULATOR_DIGITAL_IN ?
if(UART_COM_PORT_IES & MODULATOR_DIGITAL_IN) {// caused by high-low transmission ?
BitFreq = _1850HzBitFreq; // load logical 0 value into modulation register
LED_PORT_OUT &= ~DATA_LED; // LED on
UART_COM_PORT_IES &= ~MODULATOR_DIGITAL_IN;// change pin isr edge sensivity
} else {
BitFreq = _1650HzBitFreq; // load logical 1 value into modulation register
LED_PORT_OUT |= DATA_LED; // LED off
UART_COM_PORT_IES |= MODULATOR_DIGITAL_IN; // change pin isr edge sensivity
}
UART_COM_PORT_IFG &= ~MODULATOR_DIGITAL_IN; // clear interrupt flag
} else {
UART_COM_PORT_IFG = 0;
}
}

2  FSK 解调制
经过运算放大器信号放大后,将接收到的频率信号通过引脚P2.3传入比较器,比较器A将接收到的信号与内部参考电压Vcc/2比较。可以通过定时器A的捕获/比较1Timer_A.CCR1模块,计算出接收到信号的频率。下面是CCR1捕获中断服务程序的流程图。
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
 中断服务程序计算相邻两个上升沿或相邻两个下降沿之间的定时器定时的时间,即计算信号的周期值,然后与‘MARK’(980Hz, '1'信号)和‘SPACE’(1180Hz, ‘0’信号)的周期值进行比较(当然在一定的误差范围内),判断收到的应该是‘0’信号还是'1'信号。周期值的计算可以依照下面的公式计算:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
 下面的表格给出了频率不交的误差范围:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
 MSP430相关代码:

pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1(void) {

static signed int Prev_negEgdeCapture = 0;
static signed int Prev_posEgdeCapture = 0;
static unsigned char EdgeCounter = 0;
signed int CCR1_Capture;
signed int Capture_Diff;

switch(TAIV) {
// CCR1 interrupt handler
case 2:
CCR1_Capture = TACCR1;
if(ModemStatusReg & POSITIVE_EDGE) {
Capture_Diff = CCR1_Capture - Prev_posEgdeCapture;
Prev_posEgdeCapture = CCR1_Capture;
ModemStatusReg &= ~POSITIVE_EDGE;
} else {
Capture_Diff = CCR1_Capture - Prev_negEgdeCapture;
Prev_negEgdeCapture = CCR1_Capture;
ModemStatusReg |= POSITIVE_EDGE;
}

if(Capture_Diff > RX_FREQ_CHN1_SPACE-CHN1_MARGIN && Capture_Diff < RX_FREQ_CHN1_SPACE+CHN1_MARGIN) {
if(HandshakeStateMachine == DetectOnes)
EdgeCounter = 0;
// 0 detected
zeros++;
ModemStatusReg |= OFF_HOOK;
} else if(Capture_Diff > RX_FREQ_CHN1_MARK-CHN1_MARGIN && Capture_Diff < RX_FREQ_CHN1_MARK+CHN1_MARGIN) {
// handle detection of binary ones during negotiation handshake
if(HandshakeStateMachine == DetectOnes) { // are we performing the negotiation handshake?
EdgeCounter++; // increment counter
if(EdgeCounter == DetectTime_Chn1) { // sufficient edges detected?
HandshakeStateMachine = OnesDetected; // change to next negotiation handshake state
}
}
// 1 detected
ones++;
ModemStatusReg |= OFF_HOOK;
}
if(zeros>=6 && ModemStateMachine == DataMode && !(ModemStatusReg & STARTBIT)) {
ModemStatusReg |= STARTBIT; // startbit detected
BitCounter = 0;
zeros = 0; // reset counters
ones = 0;
UART_COM_PORT_OUT &= ~DEMODULATOR_DIGITAL_OUT; // show startbit to UART
LED_PORT_OUT &= ~DATA_LED;
TACCTL0 = CCIE;
TACCR0 = CCR1_Capture + BAUDRATE;
}
break;
}
}
代码中,只要检测6个‘SPACE’('0'信号),就表示收到了数据的起始位。此时,定时器Timer_A.CCR0 捕获/比较块设置成比较模式,通过引脚P2.3接收数据。只要收到数据,就开始触发定时时间为1/300s的在定时器中断,在该中断函数中,根据收到的是‘SPACE’信号还是'MAKR'信号,设置引脚P1.2的高低电平。具体程序流程图如下:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
MSP430实现的代码如下:

#pragma vector=TIMERA0_VECTOR
__interrupt void TA_CCR0_ISR(void) {

static unsigned int HandshakeCounter = 0;

// DataMode
if((ModemStatusReg & STARTBIT) && ModemStateMachine == DataMode) {
BitCounter++;
if(BitCounter == 9) { // processed one byte ?
TACCTL0 = 0; // stop bit detection trigger
ModemStatusReg &= ~STARTBIT;
UART_COM_PORT_OUT |= DEMODULATOR_DIGITAL_OUT; // show stopbit to UART
LED_PORT_OUT |= DATA_LED; // LED off
} else {
if(ones >= zeros) {
UART_COM_PORT_OUT |= DEMODULATOR_DIGITAL_OUT; // show 1 to UART
LED_PORT_OUT |= DATA_LED; // LED off
} else {
UART_COM_PORT_OUT &= ~DEMODULATOR_DIGITAL_OUT;// show 0 to UART
LED_PORT_OUT &= ~DATA_LED; // LED on
}
}
zeros = 0;
ones = 0;
}

.......

}

引脚P1.2成功将原来的频率信号转化成二进制数字信号,然后直接将引脚P1.2与串口0的接收引脚相连,这样的话我们就可以直接在串口缓冲中读取收到的数据。信号转换后的图形如下:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
 FSK解调制的过程可以下面的图来表示:
基于MSP430的FSK 调制与解调制技术 - ziye334 - ziye334的博客
总结
上面主要讲了代码实现FSK的调制与解调制的思路,但是如果想要做出产品还需要努力。比如想做一个类似“卡拉卡”的产品,除了单片机这边需要你编写FSK调制与解调制代码外,手机端还要编写相关的软件。一般来说,这需要至少两个人,一个做底下单片机相关部分编程,另一个做手机端软件编程,因为上下都精通的大牛少之又少 。

关键字:MSP430  FSK  调制  解调制技术

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/article_2016101030306.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:基于MSP430的低功耗便携式测温仪设计
下一篇:MSP430 PWM

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

Nokia LCD 5110 移植(基于MSP430F5529)

头文件nokia_5110.h#ifndef __nokia_5110_h_#define __nokia_5110_h_#include <msp430.h>#define LCD_5110_DIR            P3DIR#define LCD_5110_OUT        P3OUT#define   LCD_RST    2#define   LCD_CE    3#define   
发表于 2019-05-11

SPWM波在单片机上的实现与调节(基于MSP430F5529)

);extern void SPWM_2Way_Init(void);extern void SPWM_2Way_Set_Freq(unsigned int freq);#endif /* PWM_H_ */头文件include.h/* * include.h * *  Created on: 2016-8-18 *      Author: Flyskyr */#include <msp430.h>#include"PWM.h"unsigned int spwm_i,spwm_j;unsigned int
发表于 2019-05-11

按键的长按与短按(基于MSP430F5529)

长按与短按的区别只是加上一个适当的延时然后再去判断引脚状态。定义:#define KEYDIR P2DIR#define KEYIN P2IN#define KEYIFG P2IFG#define KEYIE P2IE#define KEYIES P2IES#define KEYREN P2REN#define S1 BIT0extern unsigned char key_key;在中断中处理长按与短按:#pragma vector=PORT2_VECTOR  //声明中断向量地址__interrupt void GPIOIntHandler(void){unsigned int IntState,vextend,cv
发表于 2019-05-11

关于MSP430的ADC中断相关问题

在进行MSP430ADC相关代码操作的时候,遇到一个百思不得其解的问题,我们按照要求设置好ADC通道,ADC中断,程序始终无法进入到ADC中断中去,本人一次又一次确认通道选择是否出错,中断是否设置,但是依然无法进入中断,经过试验和搜索,终于找到了问题所在。MSP430的ADC12IE寄存器虽然是用来使能各个ADC中断的,但是在单通道转换模式下,无论你使用的是哪个ADC通道,ADC12IE对应的中断只能是0x01,对应的中断标志位为ADC12IFG0,并且只能在ADC12MEM0中读取ADC的值。下面给出一个单通道转换的实例:#include "msp430x54x.h"unsigned int adc;void
发表于 2019-05-07

基于MSP430内部10位ADC的模数转化并通过串口发送

//******************************************************************************//  MSP-FET430P140 Demo - ADC12, Using the Internal Reference////  Description: //////                MSP430F149//             ---------------// 
发表于 2019-05-07

msp430学习笔记之定时器A

下一事件发生的时间在当前中断程序中加到CCRx中,如图4,下次发生中断的时间等于在CCR0a发生中断时刻,CCR0 = CCR0a + Δt图 4 连续计数模式下中断与CCRx关系4 增减计数模式(产生两个中断标志)当计数器计数到跟TACCR0一样的之后,然后从TACCR0开始又减少,直到为零,然后又开始增。当计数跟TACCR0一样的时候产生一个中断标志CCIFG,当减到为零的时候又产生一个中断标志TAIFG。如图:图 5 增减计数模式时序图相关寄存器这里就不一一介绍了,可以翻阅数据手册2 代码实现//本平台 msp430f149#include <msp430f149.h> volatile unsigned
发表于 2019-05-07
msp430学习笔记之定时器A

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved