MSP430中printf()重定向输出
Posted 这还能重名?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MSP430中printf()重定向输出相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、时钟配置
#include "clock.h"
//主系统目标时钟频率(单位kHz)
#define MCLK_target_kHz 25000
//主系统时钟频率与FLL源的比值
#define MCLK_inFLL_Ratio 763
uint16_t status;//振荡器状态标志
void clock_init(void)
{
PMM_setVCore(PMM_CORE_LEVEL_1);//设置核心电压
PMM_setVCore(PMM_CORE_LEVEL_2);
PMM_setVCore(PMM_CORE_LEVEL_3);
//XT1晶振输入引脚
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN4+GPIO_PIN5);
//在低频模式下初始化XT1晶体振荡器
UCS_turnOnLFXT1(UCS_XT1_DRIVE_0,UCS_XCAP_3);
// GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1,GPIO_PIN0);//辅助时钟输出引脚
// GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2,GPIO_PIN2);//子系统时钟输出引脚
// GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P7,GPIO_PIN7);//主系统时钟输出引脚
//FLL的时钟来源为不分频的内部低频振荡器(32.768kHz)
UCS_initClockSignal(UCS_FLLREF,UCS_XT1CLK_SELECT,UCS_CLOCK_DIVIDER_1);
//辅助时钟的来源为不分频的内部振荡器
UCS_initClockSignal(UCS_ACLK,UCS_XT1CLK_SELECT,UCS_CLOCK_DIVIDER_1);
//子系统的时钟为主时钟的一半
UCS_initClockSignal(UCS_SMCLK,UCS_DCOCLK_SELECT,UCS_CLOCK_DIVIDER_2);
//设置主时钟的频率(单位kHz)和比率,初始化DCO
UCS_initFLLSettle(MCLK_target_kHz,MCLK_inFLL_Ratio);
SFR_clearInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);//清除振荡器故障中断标志
SFR_enableInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);//开启振荡器故障中断
__bis_SR_register(GIE);//使能全局中断
}
#pragma vector=UNMI_VECTOR
__interrupt void NMI_ISR(void)
{
do
{
status = UCS_clearAllOscFlagsWithTimeout(1000);
}while(status != 0);
}
首先对时钟的配置,如上所示,当频率高于12MHz的时候,提高核心电压的等级,否则产生的时钟不稳定,需要注意的是,需要一级一级的提升,不能一开始就提高到3级,代码中使用了外部的XTI(32.768KHz)作为时钟源,原因是内部晶振不稳定,受温度的影响大,而外部的晶振比较稳定。特别是涉及到通信的时候,晶振的不稳定会对通信产生很大的影响。
二、串口配置
#include "usart.h"
int fputc(int ch,FILE *f)
{
USCI_A_UART_transmitData(USCI_A0_BASE,(uint8_t)ch);
while(USCI_A_UART_getInterruptStatus(USCI_A0_BASE,USCI_A_UART_TRANSMIT_INTERRUPT_FLAG) == UCTXIFG);
return ch;
}
int fputs(const char *_ptr,register FILE *_fp)
{
uint16_t i,len;
len = strlen(_ptr);
for(i=0;i<len;i++)
{
USCI_A_UART_transmitData(USCI_A0_BASE,(unsigned char)_ptr[i]);
while(USCI_A_UART_getInterruptStatus(USCI_A0_BASE,USCI_A_UART_TRANSMIT_INTERRUPT_FLAG) == UCTXIFG);
}
return len;
}
void usart_init(uint32_t clock,uint32_t baud)
{
double clockPrescalar_val_temp,secondModReg_val_temp;
uint16_t clockPrescalar_val,secondModReg_val;
clockPrescalar_val_temp = (double)((clock * 1.0)/(baud * 1.0));
clockPrescalar_val = (uint16_t)(clockPrescalar_val_temp);
secondModReg_val_temp = (clockPrescalar_val_temp - clockPrescalar_val * 1.0) * 8;
secondModReg_val = (uint16_t)(secondModReg_val_temp) + 1;
if( (secondModReg_val_temp+0.5) >= secondModReg_val)
{
secondModReg_val = secondModReg_val;
}
else
{
secondModReg_val = secondModReg_val - 1;
}
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,GPIO_PIN3 + GPIO_PIN4);//输出复用
USCI_A_UART_initParam param = {0};
param.clockPrescalar = clockPrescalar_val;//1.048MHz/9600取整
param.firstModReg = 0;//过采样波特率时使用
param.msborLsbFirst = USCI_A_UART_LSB_FIRST;//LSB
param.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;//一个停止位
param.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;//低采样波特率
param.parity = USCI_A_UART_NO_PARITY;//无奇偶校验位
param.secondModReg = secondModReg_val;// {(1.048MHz/9600)-int(1.048MHz/9600)} * 8 = val ,然后再对val四舍五入取整。
param.selectClockSource =USCI_A_UART_CLOCKSOURCE_SMCLK;//串口时钟的来源来自子系统时钟
param.uartMode = USCI_A_UART_MODE;//串口模式
#if Tx_Interrupt
USCI_A_UART_enableInterrupt(USCI_A0_BASE,USCI_A_UART_TRANSMIT_INTERRUPT);//开启串口发送中断
#endif
#if Rx_Interrupt
USCI_A_UART_enableInterrupt(USCI_A0_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//开启串口接收中断
#endif
if (STATUS_FAIL == USCI_A_UART_init(USCI_A0_BASE, ¶m))
{
return;
}//等待串口模块初始化完成
USCI_A_UART_clearInterrupt(USCI_A0_BASE,USCI_A_UART_TRANSMIT_INTERRUPT_FLAG);//清除串口发送完成标志
USCI_A_UART_clearInterrupt(USCI_A0_BASE,USCI_A_UART_RECEIVE_INTERRUPT_FLAG);//清除串口接收完成标志
USCI_A_UART_enable(USCI_A0_BASE);//使能串口模块
}
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR (void)
{
switch (__even_in_range(UCA0IV,4))
{
case 0:break;//没有中断
case 2:
{
USCI_A_UART_clearInterrupt(USCI_A0_BASE,USCI_A_UART_RECEIVE_INTERRUPT_FLAG);
};break;//接收中断
case 4:
{
USCI_A_UART_clearInterrupt(USCI_A0_BASE,USCI_A_UART_TRANSMIT_INTERRUPT_FLAG);
};break;//发送中断
default: break;
}
}
此处需要注意的地方有两点。第一,需要开启串口的发送中断和接收中断,否则串口不工作(未找到原因)。第二,在使用printf()重定向时,初始化的顺序尤其重要!!!
我们将上面正确的初始化程序调整一下,运行的结果如下图所示:
可以看出出现了乱码。当使用串口打印中文时,会出现乱码,很大的可能是CCS使用的编码格式和串口助手使用的编码格式不同。
修改工程的编码格式如下:
选中工程右键选择最底部的Properties选项(或者快捷键ALT+Enter),
以上是关于MSP430中printf()重定向输出的主要内容,如果未能解决你的问题,请参考以下文章