部件号:MSP-EXP432P401R
工具/软件:TI C/C++编译器
实时FIR过滤,具有三重缓冲
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h> //exact-width整数类型
#include <ti\devices\msp432p4xx\driverlib\driverlib.h>// 驱动程序库
#define clock_hf 4800万 //48MHz
#define clock_lf 3.2万 //32kHz
#define TIMER0_FREQ 1 //单位:Hz
#define sample_FREQ 8000//频率(以Hz为单位),数字音频的通用采样率:800.032万3200.0441万4410.048万00
#define MCP4921_SPI_bitrate 20e6 //needs to > sample_FREQ*16和< SMCLK/2,max 20M
#define MCP4921_SPI_DATA_MASK 0x0FFF //请参阅数据表MCP4921
#define MCP4921_SPI_CTRL_MASK 0x7000 //请参阅数据表MCP4921
#define red_LED gPIO_PIN0
#define green_LED gPIO_PIN1
#define blue_LED GPIO
#define NUM_DISP_TEX_LINE 4.
//三重缓冲的定义。
#define NUM_DATA_BUFFER 3.
#define data_buffer_LEN 200
#define filter_LEN_M 28.
//函数原型
void initDevice_HFXT(void);
void initGPIO (void);
void initTimer(void);
void initUART(void);
void initADC14(void);
void initSPI(void);
void initDataBuffer(void);
void processData (void);
void uart0_searstr(const char *str);
//全局变量
uINT32_t clockMCLK,clockSMCLK;
uINT8_t当前LED =红色LED;
volatile UINT32_t dataBuffer[NUM_DATA_BUFFER][DATA_BUFFER_LEN];
volatile UINT32_t buf_inputIndex=0,buf_outputIndex=1,buf_dataIndex=2;
volatile buf_dataReady=false,buf_overrunError=false;
FLOAT FILTER_BCOef[FILTER_LEN_M+1]=
{
0.0.14541062亿 ,0.0012749733 ,0.0009739225 ,0.0.00396414亿 ,0.0.24743259亿 ,
0.0.70030369亿 ,0.0140943302 ,0.0238646359 ,0.3.59851042亿 ,0.4.9667346亿 ,
0.6.37372145亿 ,0.0767880565 ,0.0873882711 ,0.9.43060927亿 ,0.9.67098938亿 ,
0.9.43060927亿 ,0.0873882711 ,0.0767880565 ,0.6.37372145亿 ,0.4.9667346亿 ,
0.3.59851042亿 ,0.0238646359 ,0.0140943302 ,0.0.70030369亿 ,0.0.24743259亿 ,
0.0.00396414亿 ,0.0009739225 ,0.0012749733 ,0.0.14541062亿
};
const char *terminalDisplayText[NUM_DISP_TEFY_LINE]=
{
"\r\n",
"使用三重缓冲进行实时FIR过滤\r\n ",
"R:红色,G:绿色,B:蓝色,H:帮助\r\n",
">"
};
Void主(void)
{
uINT32_t i;
UINT8_t数据;
initDevice_HFXT();
initGPIO ();
initTimer();
initUART();
initADC14();
initSPI();
initDataBuffer();
interrup_enableMaster();
Timer32_startTimer(TIMER32_0_base, false);
Timer32_startTimer(TIMER32_1_base, false);
//终端上的初始显示。
for (i=0;i<NUM_DISP_TEXT_LINE;i++)
{
uart0_terminalDisplayText[I];
}
同时(1)
{
IF (UART_getInterruptStatus (EUSCI_A0_BASE,EUSCI_A_UART_receive中断标志)
{
数据= UART_receiveData(EUSI_A0_base);
UART_clearInterruptFlag (EUSCI_A0_BASE,EUSCI_A_UART_receive中断标志);
交换机(数据)
{
案例'R':
案例'r':
currentLED = red_LED;
uart0_senderStr ("红色闪烁LED。\r\n>");
中断;
案例'G':
案例'g':
当前LED =绿色_LED;
uart0_sedrStr ("闪烁绿色LED。\r\n>");
中断;
案例'B':
案例'b':
currentLED = blue_LED;
uart0_sedrStr ("蓝色闪烁LED。\r\n>");
中断;
案例'H':
案例'h':
for (i=0;i<NUM_DISP_TEXT_LINE;i++)
{
uart0_terminalDisplayText[I];
}
中断;
}
}//IF结束
IF (buf_overrunError)
{
//此错误表示processData()例程需要太多时间才能完成。
//优化此例程以更快地运行或将buffer_LEN设置为更大。
//uart0_sedrStr ("错误:缓冲区溢出!\r\n");
printf ("错误:缓冲区溢出!\r\n");
buf_overrunError =假;
}
IF (buf_dataReady)
{
processData();
buf_dataReady =假;
}
}//while结束
}
void initDevice_HFXT(void)
{
WDT_A_HoldTimer();// 停止监视程序计时器
//将VCORE更改为1以支持高于24MHz的频率。
//有关给定频率的闪存等待状态要求,请参见数据表。
PCM_setPowerState (PCM_AM_DCDC_VCORE1);
Flashctl_setWaitState(flash_BANK0, 1);
Flashctl_setWaitState(flash_Bank1,1);
FPU_enableModule();
FPU_enableLazyStacking();//需要在ISR内使用FPU。
//在HFXT模式下配置PJ.2和PJ.3。
//初始化外部时钟源HFXT。
GPIO_setAsPeripheralModuleFunctionOutputPin (GPIO端口PJ,GPIO PIN2|GPIO _PIN3,GPIO主要模块功能);
cs_setExternalClockSourceFrequency(clock_lf,Clock_hF);
cs_startHFXT (FALSE);
cs_initClockSignal (CS_MCLK,CS_HFXTCLK_SELECT,CS_Clock_diver_1);
cs_initClockSignal (CS_HSMCLK,CS_HFXTCLK_SELECT,CS_Clock_diver_16);
cs_initClockSignal (CS_SMCLK,CS_HFXTCLK_SELECT,CS_Clock_diver_1);//48MHz支持SPI
clockMCLK = CS_getMCLK();
clockSMCLK = CS_getSMCLK();
}
void initGPIO (void)
{
//将WFP 2.0 ,WFP 2.1 ,2.2 配置为输出。
//WFP,2.0 2.1 ,WFP,2.2 与LaunchPad上的RGB三色LED相连。
GPIO _setAsOutputPin (GPIO端口P2,GPIO _PIN0|GPIO _PIN1|GPIO _PIN2);
}
void initTimer(void)
{
// TIMER32_0闪烁心跳LED
Timer32_initModule (TIMER32_0_BASE,TIMER32_prescaler_1,TIMER32_32bit,TIMER32_Periodic_mode);
Timer32_setCount (TIMER32_0_BASE,clockMCLK/TIMER0_FREQ - 1);
Timer32_enableInterrupt (TIMER32_0_BASE);
InterrupT_enableInterrupt (INT_T32_INT1);//在中断控制器中启用Timer32_0中断。
// TIMER32_1执行输入/ADC和输出/DAC
Timer32_initModule (TIMER32_1_BASE,TIMER32_prescaler_1,TIMER32_32bit,TIMER32_Periodic_mode);
Timer32_setCount (TIMER32_1_BASE,clockMCLK/sample_FREQ -1);
Timer32_enableInterrupt (TIMER32_1_BASE);
InterrupT_enableInterrupt (INT_T32_INT2);//在中断控制器中启用Timer32_1中断。
}
void initUART (void)
{
//配置为48MHz SMCLK,11.52万波特率。
//使用TI提供的在线计算器计算得出:
software-dl.ti.com/.../index.html
CONST eUSI_UART_Config =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK,//SMCLK时钟源,48MHz
26,//BRDIV
0,//UCxBRF
111,//UCXBRS
EUSCI_A_UART_NO_PARity,//无奇偶校验
EUSCI_A_UART_LSB_FIRST,//MSB FIRST
EUSCI_A_UART_ONE_STOP_BIT,//一个停止位
EUSCI_A_UART_MODE,//UART模式
EUSCI_A_UART_oversampling_BAUDRATE_generation //Oversampling
};
//为UART配置GPIO引脚。 美国国家公园(1.2),德克萨斯州:美国国家公园(1.3)。
GPIO _setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P1, GPIO _PIN2|GPIO _PIN3,GPIO主要模块功能);
UART_INITModule (EUSCI_A0_BASE,&config);
UART_enableModule (EUSCI_A0_BASE);
}
//使用WFP 6.1 / A14进行采样
void initADC14(void)
{
ADC14_enableModule();
ADC14_INITModule (ADC_CLOCKSOURCE_SMCLK,ADC_PREDIVIDER_1,ADC_DIVIDER_1,ADC_NOROUTE);
//将WFP 6.1 配置为A14
GPIO _setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P6,GPIO _PIN1,GPIO第三模块功能);
ADC14_setResolution (ADC_12位);
ADC14_configureSingleSampleMode (ADC_MEM0,TRUE);//repeatMode = TRUE
ADC14_configureConversionMemory (ADC_MEM0,ADC_VREFPOS_AVCC_VREFNEG_VSS,ADC_INPUT_A14,FALSE);
//请参阅技术参考第20.2 章节6了解样例正时注意事项。
ADC14_enableSampleTimer(ADC_MANUAL_ITED);
ADC14_setSampleHoldTime (ADC_PULSE_WIDES_4,ADC_PULSE_WIDES_4);
ADC14_enableConversion();
}
void initSPI(void)
{
Const eUSI_SPI_MasterConfig spiMasterConfig =
{
EUSCI_B_SPI_CLOCKSOURCE_SMCLK, //SMCLK时钟源
clockSMCLK, //时钟源频率
MCP4921_SPI_bitrate, //desedSpiClock
EUSCI_B_SPI_MSB_FIRST, //MSB FIRST
EUSCI_B_SPI_PHASE DATA_Changed_ONFIRST_Captured_on_NEXT ,//相位
EUSCI_B_SPI_CLOCKPOLARITY_INACILY_LOW, //极性低
EUSCI_B_SPI_3pin //3Wire SPI模式
};
//WFP 1.5 :SCK, WFP 1.6 :SDI,WFP 5.2 :CS
GPIO _setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P1, GPIO _PIN5|GPIO _PIN6,GPIO主要模块功能);
GPIO _setAsOutputPin (GPIO端口P5,GPIO _PIN2);
GPIO _setOutputHighOnPin (GPIO端口P5,GPIO _PIN2);
//在3Wire主模式下配置SPI
SPI_initMaster(EUSI_B0_BASE,&spiMasterConfig);
//启用SPI模块
SPI_enableModule(EUSI_B0_BASE;
}
void initDataBuffer(void)
{
uINT32_t i,j;
for (i=0;i<NUM_DATA_BUFFER;i++)
{
对于(j=0;j<数据缓冲器_LEN;j++)
{
dataBuffer[I][j]= 0;
}
}
}
void processData (void)
{
静态浮点数据[DATA_BUFFER_LEN + FILTER_LEN_M]={0};//增强数据帧,初始化为0
浮子y;
uINT32_t *pBuf =(UINT32_t *) dataBuffer[buf_dataIndex];
uINT32_t i,j,k;
//将数据从数据帧复制到增强数据帧。
//开始填充ATer FILTER_LEN_M元素。
对于(i=0,j=filter_LEN_M;i<data_buffer_LEN;i++,j++)
{
data[j]=(浮点) pBuf[i];
}
// FIR过滤:y[n]= sum_{i=0}^{M}(B[i]x[n-I])。
对于(i=0;i<data_buffer_LEN;i++)
{
Y = 0;
用于(j=0,k=i;j<=filter_LEN_M;j++,k++)
{
y += FILTER_BCOef[j]*DATA[k];
}
pBuf[i]=(UINT32_t) y;
}
//将最后一个FILTER_LEN_M样本数保存到增强数据帧的开头。
对于(i=0;i<filter_LEN_M;i++)
{
data[i]= data[data_buffer_LEN+i];
}
}
//通过UART0传输字符串。
void uart0_searstr(const char *str)
{
uINT32_t长度,i=0;
len = strlen (str);
同时(我< len)
{
UART_HESRData (EUSCI_A0_BASE,STR[I++]);
while (!UART_getInterruptStatus (EUSCI_A0_BASE,EUSCI_A_UART_Transmit_Complete_InterrupT_flag));
UART_clearInterruptFlag (EUSCI_A0_BASE,EUSCI_A_UART_Transmit_Complete_InterrupT_flag);
}
}
//Timer32_0 ISR
void T32_INT1_IRQHandler (void)
{
Timer32_clearInterruptFlag (TIMER32_0_BASE);
IF (GPIO _getInputPinValue (GPIO端口P2,GPIO _PIN0|GPIO _PIN1|GPIO _PIN2))
{
GPIO _setOutputLowOnPin (GPIO端口P2,GPIO _PIN0|GPIO _PIN1|GPIO _PIN2);
}
否则
{
GPIO_setOutputHighOnPin (GPIO端口P2,当前LED);
}
}
//Timer32_1 ISR
void T32_INT2_IRQHandler (void)
{
静态UINT32_t样本索引=0;
uINT32_t tmpIndex;
UINT16_t数据;
uINT8_t字节1,字节0;
Timer32_clearInterruptFlag (TIMER32_1_BASE);
//从ADC读取。
ADC14_toggleConversionTrigger();
while (!(ADC_INT0 & ADC14_getInterruptStatus());
ADC14_clearInterruptFlag(ADC_INT0);
dataBuffer[buf_inputIndex][sampleIndex]= ADC14_getResult(ADC_MEM0);
//为SPI准备数据。
数据= MCP4921_SPI_CTRL_MASK |(MCP4921_SPI_DATA_MASK & dataBuffer[buf_outputIndex][sampleIndex]);
字节1 =(uint8_t)(data>>8);
byte0 =(uint8_t)数据;
//SPI使用寄存器级操作编写,以支持16位操作。
p5->out &=~BIT2;//在SPI从属设备上将CS设置为LOW。
EUSCI_B0->TXBUF =字节1;//传输字节1
EUSCI_B0->TXBUF =字节0;//传输字节0
while (!(EUSSCI_B0->IFG & EUSCI_B_IFG_TXIFG));//检查TX缓冲区是否就绪。
p5->out || BIT2;//在SPI从属设备上将CS设置为HIGH。
//更新缓冲区索引和样本索引。
IF (++sampleIndex >= DATA_BUFFER_LEN)
{
样本索引=0;
IF (buf_dataReady)
{
buf_overrunError =真;
}
tmpIndex = buf_inputIndex;
buf_inputIndex = buf_outputIndex;
buf_outputIndex = buf_dataIndex;
buf_dataIndex = tmpIndex;
buf_dataReady =真;
}
}
问题2. 如何使用Matlab执行FIR滤波器设计。
1•在Matlab中,使用“filterDesigner”设计低通FIR等波滤波器,顺序为50=M,采样频率为kHz 8=SF,带式切断频率为Hz 1500=passF,带式切断频率为Hz 2000=stopF,带式和带式的重量均为1。 将设计的过滤器作为系数变量导出到Matlab工作区,并使用Matlab函数“plot”绘制其时间域单位样本响应,并使用Matlab函数“freqz”绘制其频率响应。
2•创建新的CCS项目“Lab9_2”。 将示例代码“Lab9_1_main.c”添加到项目中。 •本实验的输入和输出设置与问题1完全相同。
3•将“Lab9_1_main.c”中使用的过滤器替换为刚刚设计的新FIR过滤器。 “Lab9_1_main.c”中的某些参数/变量值需要根据新过滤器的规范进行更改。 •使用问题1中的测试信号重复滤波实验步骤,以测试新FIR滤波器设计的实施情况。 •在报告中解释您的代码和实验结果。
问题3. 使用Ping Pong缓冲进行实时FIR过滤。
•创建新的CCS项目“Lab9_3”。 •本实验的输入和输出设置与问题1完全相同。 •使用Ping-Pong缓冲技术实现与Lab9_2中相同的实时FIR过滤功能。 •在您的报告中解释基于Ping Pong缓冲的FIR过滤是如何工作的。 •在报告中解释您自己的代码。