MSP430 标准库printf函数实现
2011-08-02 21:22
关键是增加一个putchar函数。
代码如下:
#include
#include
void NOP10(void)
{
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
}
int putchar( int c )//注意不要改参数的类型和返回值的类型,否则printf 调用是就有问题了。
{
if (c == '\n')
{
TXBUF1 = '\r';
while((UTCTL1&0x01)==0);
}
TXBUF1 = c;
while((UTCTL1&0x01)==0);
return c;
}
void InitalUart1(void)
{
P4SEL |= 0x03; // P4.0,1 = USART1 TXD/RXD ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD UCTL1 |= CHAR; // 8-bit character
UTCTL1 |= SSEL1; // UCLK = SMCLK
UBR01 = 0x36; // 1MHz 19200
UBR11 = 0x00; // 1MHz 19200
UMCTL1 = 0x6B; // Modulation
UCTL1 &= ~SWRST; // Initalize USART state machine
IE2 |= URXIE1; // Enable USART1 RX interrupt
//IFG2 |= UTXIFG1;
}
void main(void)
{
unsigned char i;
i=0x10;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
FLL_CTL0 |= XCAP18PF; // Configure load caps
InitalUart1();
_EINT();
// LPM0;
while(1)
{
// while (!(IFG2 & UTXIFG1)); // USART1 TX buffer ready?
// TXBUF1 = 'H';
//putchar(0x05);
//putchar('c');
printf("%d",i);
NOP10();
}
}
#pragma vector=USART1RX_VECTOR
__interrupt void usart1_rx(void)
{
while (!(IFG2 & UTXIFG1)); // USART1 TX buffer ready? TXBUF1 = RXBUF1; // RXBUF1 to TXBUF0
//LPM0_EXIT;
msp430各模块函数整合(1)
2010-08-13 14:27
/***************************************************
程序功能:控制8个LED闪烁,用于测试下载功能是否正常
测试说明:观察LED闪烁
***************************************************/
#include
#include "EEPROM.c"
#include "LCD1602.c"
#include "DS18B20.c"
void LED_delay(unsigned int dly);
void KEY_delay(void);
void EEPROM_delay(unsigned int ts);
void sys_init(void);
void LED_Init(void);
void LED_Set(unsigned char LED_Status);
unsigned char LED_Read_Status(void);
void LED_Test(void);
void KEY_Init(void);
unsigned char key(unsigned char c);
void KEY_Test(void);
void SEG_Init(void);
void SEG_Show(unsigned char num,unsigned char SEG_Data);
void EEPROM_Init(void);
void Write_EEPROM(uchar address,uchar *databuf,uchar num);
void Read_EEPROM(uchar address,uchar *databuf,uchar num);
void LCD1602_Init(void);
void LCD1602_Show(uchar *databuf,uchar num);
void DS18B20_Init(void);
void TimerA_Delay_CFG(void);
float get_DS18B20_temperature(void);
unsigned char SEG_Table[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//0-f段选信号,共阳
uchar UART_Rev_String[20]="\0";
uchar rev_string_count=0;
uchar rev_string_complete=0; //为1代表串口接收了一行字符串
// ==================================================================
// 延时函数
// ==================================================================
//*************************************************
// function : LED_delay
// parameter : dly(延时值)
// description : 用于LED花样显示延时
//*************************************************
void LED_delay(unsigned int dly)
{
unsigned int i;
while(dly--)
for(i=8000;i>0;i--);
}
//*************************************************
// function : KEY_delay
// parameter : (无)
// description : 用于消抖的延时
//*************************************************
void KEY_delay(void)
{
uint tmp;
for(tmp = 12000;tmp > 0;tmp--);
}
//*************************************************
// function : EEPROM_delay
// parameter : ts(延时值)
// description : 用于消抖的延时
//*************************************************
void EEPROM_delay(unsigned int ts)
{
while(ts--);
}
// ================================================================== // 系统函数
// ==================================================================
//*************************************************
// function : sys_init
// parameter : (无)
// description : 延时一段时间
//*************************************************
void sys_init(void)
{
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
BCSCTL2 &=0xc0; //XT2CLK+2分频
// ==================================================================
// LED相关函数
// ==================================================================
//*************************************************
// function : LED_Init
// parameter : (无)
// description : LED初始化程序
// 8个LED接在P2.0~P2.7上。
//*************************************************
void LED_Init(void)
{
P2SEL = (0x00); //相应位为0代表普通IO口功能
P2DIR = (0xff); //相应位为1代表输出功能
P2OUT = (0xff); //从原理图可知,当P2相应端口为高电平时LED亮
LED_delay(10);//我们设置灯初始为闪烁一次
P2OUT = (0x00);
LED_delay(10);
}
//*************************************************
// function : LED_Set
// parameter : LED_Status(一个8位的数据,每一位对应P2的每个端口) // description : 配置8个LED的状态
//*************************************************
void LED_Set(unsigned char LED_Status)
{
P2DIR = (0xff); //相应位为1代表输出功能
P2OUT = (LED_Status);//配置八个LED灯的状态
}
//*************************************************
// function : LED_Read_Status
// parameter : (无)
// description : 读出8个LED的状态
//*************************************************
unsigned char LED_Read_Status(void)
{
unsigned char temp;
P2DIR = (0xff); //配置八个LED灯的状态
temp = P2IN;
return temp;
// 0xff : 1111 1111
// 0x7e : 0111 1110
// 0x3c : 0011 1100
// 0x18 : 0001 1000
// 0x00 : 0000 0000
// 0x18 : 0001 1000
// 0x24 : 0010 0100
// 0x42 : 0100 0010
// 0x81 : 1000 0001
// 0x00 : 0000 0000
void LED_Test(void)
{
unsigned char LED_Table[10]={0xff,0x7e,0x3c,0x18,0x00,0x18,0x24,0x42,0x81,0x00}; unsigned char count;
LED_Init();
//第一种花样显示
for(count=0;count<10;count++)
{
LED_Set(LED_Table[count]);
LED_delay(10);
}
//第二种花样显示
for(count=0;count<7;count++)
{
LED_Set(0x01<<(count));
LED_delay(10);
}
for(count=0;count<7;count++)
{
LED_Set(0x80>>(count));
LED_delay(10);
}
}
// ==================================================================
// KEY相关函数
// ==================================================================
//*************************************************
// function : KEY_Init
// parameter : (无)
// description : 键盘初始化程序
//*************************************************
void KEY_Init(void)
{
P5SEL &= 0x0f;//通用功能
P5DIR = 0xf0;//输出
P1SEL &= 0x00;//通用功能
P1DIR = 0x00;//输入
}
//*************************************************
// function : get_KEY_value
// parameter : (无)
// description : 获得当前按键的键号
//*************************************************
unsigned char key(unsigned char c)
{
if (!(P1IN&BIT0))
c+=1;
else if (!(P1IN&BIT1))
c+=2;
else if (!(P1IN&BIT2))
c+=3;
else if (!(P1IN&BIT3))
c+=4;
else c=0;
return c;
}
unsigned char get_KEY_value(void)
{
unsigned char a=0;
P5OUT = ~BIT4; //拉低P5.3
a += key(0); //如果按键在P5.3这条线上,则此处key(0)非零,然后a的值会改变,否则相当于a+=0=a
P5OUT = ~BIT5; //拉低P5.4
a += key(4); //同P5.3.但此时检测第二排键了,因此键值应该最小为4了,是要用key(4)。P5OUT = ~BIT6; //拉低P5.5
a += key(8); //检测第三排按键,要用key(8)
P5OUT = ~BIT7; //拉低P5.6
a += key(12); //检测第四排按键,要用key(12)
return a; //返回值的范围为0~f,代表1~16这些按键
}
void KEY_Test(void)
{
unsigned char key_num;
KEY_Init();
SEG_Init();
while(1)
{
key_num = get_KEY_value();
SEG_Show(1,SEG_Table[key_num]);
}
}
//*************************************************
// function : KEY_Int_Init
// parameter : (无)
// description : 键盘中断初始化
//*************************************************
void KEY_Int_Init(void)
{
P1IES |= 0x0f;
P1IE |= 0x0f;
}
//*************************************************
// function : KEY_Int
// parameter : (无)
// description : 键盘管脚KX0~3中断服务子函数
//*************************************************
#pragma vector = PORT1_VECTOR
__interrupt void KEY_Int(void)
{
uchar temp = P1IFG;
P1IFG &= 0xf0;
if(temp&0x0f) //如果KX0~3(P1.0~3)上有一个产生中断,则执行读取键值的函数。{
unsigned char key_num;
key_num = get_KEY_value();
SEG_Show(1,SEG_Table[key_num]);
}
/*
if(temp&0x01) //KX0线上的键被按下
{ }
else if(temp&0x02)//KX1线上的键被按下
{ }
else if(temp&0x04)//KX2线上的键被按下
{}
else if(temp&0x08)//KX3线上的键被按下
{}
*/
}
// ==================================================================
// Timer相关函数
// ==================================================================
//*************************************************
// function : Timer_Init
// parameter : (无)
// description : Timer初始化程序
//*************************************************
void Timer_Init(void)
{
CCTL0 = CCIE; //使能CCR0中断
CCR0 = 2047; //设定周期0.5S ,(1/32768)*8*2047=0.4997秒TACTL = TASSEL_1 + ID_3 + MC_1; //定时器A的时钟源选择ACLK,8分频,增计数模式
_EINT();
}
//*************************************************
// function : Timer_A
// parameter : (无)
// description : Timer_A中断服务程序
//*************************************************
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
// P2DIR = 0xff;
// P2OUT^=0xff; //让二极管闪
}
//*************************************************
// function : PWM_Init
// parameter : (无)
// description : 产生两路PWM波,周期为1s,可通过修改CCR0更改,占空比分别为75%和25%,可通过修改CCR1和CCR2修改
//*************************************************
void PWM_Init(void)
{
P2SEL |= BIT3 + BIT4; // P2.3和P2.4连接内部模块
CCR0 = 4096-1; // PWM周期为1S,从0开始计数
CCTL1 = OUTMOD_7; // CCR1 reset/set 翻转/置位
CCR1 = 3072; // CCR1 PWM duty cycle
CCTL2 = OUTMOD_7; // CCR2 reset/set 翻转/置位
CCR2 = 1024; // CCR2 PWM duty cycle
TACTL = TASSEL_1 + ID_3 + MC_1; // ACLK/8, up mode 32768/8=4096
}
//*************************************************
// function : Timer_DelayNus
// parameter : n(延时微秒数)
// description : 实现N个微秒的延时
//*************************************************
void Timer_DelayNus(int n)
{
TACTL = TASSEL_2 + ID_3 + MC_1; //定时器A的时钟源选择MCLK 8M,8分频,增计数模式
CCR0 = n;
TACTL |= MC_1; //增计数到CCR0
while(!(TACTL & BIT0)); //等待
TACTL &= ~MC_1; //停止计数
TACTL &= ~BIT0; //清除中断标志
}
// ==================================================================
// 七段译码显示管相关函数
// ==================================================================
//*************************************************
// function : SEG_Init
// parameter : (无)
// description : 七段译码显示管初始化程序
//*************************************************
void SEG_Init(void)
{
P4SEL &= 0x00;//通用功能
P4DIR = 0xff;//配置七段译码显示管数据线为输出
P4OUT = 0xff;//配置初始值
P4SEL &= ~(0x1f<<3);//通用功能
P6DIR |= (0x1f<<3);//配置7SEG的控制线为输出
}
//*************************************************
// function : SEG_Show
// parameter : num (指定哪个数码管)
// SEG_Data (想要显示的值)
// description : 七段译码显示管显示程序
//*************************************************
void SEG_Show(unsigned char num,unsigned char SEG_Data)
{
P1DIR |= BIT7;
P1OUT |= BIT7; //配置T_KEY1管脚,使能74LS573以用于七段译码显示管显示.
P6DIR |= (0x1f<<3);//配置7SEG的控制线为输出
P6OUT &= ~(0x1f<<3);//关闭5个7SEG。
P6OUT |= (1<<(num+2));//打开指定的7SEG。因为是从P6.3开始的,所以num要加上2
P4DIR = 0xff;//配置七段译码显示管数据线为输出
P4OUT = SEG_Data;//配置显示值
}
msp430各模块函数整合(2)
2010-08-13 14:28
// ==================================================================
// EEPROM相关函数
// ==================================================================
//*************************************************
// function : EEPROM_Init
// parameter : (无)
// description : 初始化EEPROM管脚
//*************************************************
void EEPROM_Init(void)
{
//端口默认都为普通IO口功能,此处省略PxSEL的设置
P3DIR |= BIT3 + BIT1; //设置相应端口为输出状态
P3OUT |= BIT3 + BIT1; //设置初值
}
//*************************************************
// function : Write_EEPROM
// parameter : address (写EEPROM的起始地址)
// databuf (待写入EEPROM数据的指针)
// num (待写入EEPROM数据的个数)
// description : 向EEPROM中的指定地址写入num个字节
//*************************************************
void Write_EEPROM(uchar address,uchar *databuf,uchar num)
{
unsigned int i;
for(i=address;i { EEPROM_delay(2000); //24c02写入后需要擦除操作,一定要加延时 Write_1Byte(i,databuf[i]); //功能:向EEPROM中指定地址写入1个字节的数据} } //************************************************* // function : Read_EEPROM // parameter : address (读EEPROM的起始地址) // databuf (读出的EEPROM数据的存放指针) // num (想要读出的EEPROM数据的个数) // description : 从EEPROM中的指定地址读出num个字节 //************************************************* void Read_EEPROM(uchar address,uchar *databuf,uchar num) { unsigned int i; for(i=address;i { databuf[i] = Read_1Byte_Randomaddress(i); //功能:从EEPROM中的指定地址读出1个字节的数据 //SEG_Show(1,SEG_Table[databuf[i]-48]); //在SEG上显示读出的字符 EEPROM_delay(20000); //24c02读出一字节后读下一字节前要加延时 } } void EEPROM_Test(void) { unsigned char databuf[10] = {'0','1','2','3','4','5','6','7','8','9'}; unsigned char revbuf[10]; EEPROM_Init(); SEG_Init(); Write_EEPROM(0,databuf,10); Read_EEPROM(0,revbuf,10); } // ================================================================== // LCD1602相关函数 // 硬件要求:LCD直接与单片机的A口和D口相连接 // 所有拨码开关置OFF // 调节电位器,调节LCD亮度。 // ================================================================== //************************************************* // function : LCD1602_Init // parameter : (无) // description : LCD1602初始化程序 //************************************************* void LCD1602_Init(void) { Write_LCD1602_CMD(0x38); //发送LCD1602命令,清除显示 Write_LCD1602_CMD(0x38); //发送LCD1602命令,清除显示 Write_LCD1602_CMD(0x38); //发送LCD1602命令,清除显示 Write_LCD1602_CMD(0x38); //发送LCD1602命令,清除显示 Write_LCD1602_CMD(0x08); //8位2行5*7点阵 Write_LCD1602_CMD(0x01); //显示开,光标开,闪烁 Write_LCD1602_CMD(0x06); //文字不动,光标右移 Write_LCD1602_CMD(0x0c); //文字不动,光标右移 } //************************************************* // function : LCD1602_Show // parameter : databuf (想要显示的数据指针) // num (想要显示的数据个数) // description : 在LCD1602上显示一行数据 //************************************************* void LCD1602_Show(uchar *databuf,uchar num) { unsigned int i; for(i=0;i Write_LCD1602_DATA(databuf[i]); } void LCD1602_Test(void) { LCD1602_Init(); LCD1602_Show("embedroad",9); } // ================================================================== // DS18B20相关函数 // ================================================================== //************************************************* // function : DS18B20_Init // parameter : (无) // description : 初始化DS18B20的管脚 //************************************************* void DS18B20_Init(void) { P3DIR |= BIT0; P3OUT |= BIT0; } //************************************************* // function : TimerA_Delay_CFG // parameter : (无) // description : DS18B20的延时函数使用定时器进行延时,这样可获得更精准的延时// 但也浪费了一个定时器,如果今后写代码时同时用到定时器A和 DS18B20,一定要注意两者只能选其一 // 也可以使用TimerB做定时器功能,使用TimerA给DS18B20做延时//************************************************* void TimerA_Delay_CFG(void) { //计数时钟选择SMLK=8MHz,1/8分频后为1MHz TACTL |= TASSEL_2 + ID_3; _EINT();//打开全局中断 //_DINT();//关闭中断 } //************************************************* // function : get_DS18B20_temperature // parameter : (无) // description : DS18B20获取转换值 //************************************************* float get_DS18B20_temperature(void) { unsigned int rev_temperature; float temp_temperature; rev_temperature = Do1Convert();//返回值共11位,第11位为符号位,也即零下和零上。 if(rev_temperature&(1<<11)) { temp_temperature = rev_temperature; //零下 } else { temp_temperature = ~rev_temperature; //零上 } return temp_temperature; //暂时还没想到比较好的表示方法 } // ================================================================== // UART相关函数 // ================================================================== //************************************************* // function : UART0_Init // parameter : baud (波特率) // description : DS18B20获取转换值 //************************************************* void UART0_Init(void) { P3DIR |= 0x10;//P3.4 P3.5 P3SEL |= 0x30; // 选择P3.4和P3.5做UART通信端口UCTL0 |= CHAR; // 选择8位字符 UTCTL0 |= SSEL0; // UCLK = ACLK UBR00 = 0x03; // 波特率9600 UBR10 = 0x00; // UMCTL0 = 0x4A; // Modulation UCTL0 &= ~SWRST; // 初始化UART状态机软件复位使能 ME1 |= UTXE0 + URXE0; // 使能USART0的发送和接受 IE1 |= URXIE0; //仅开启接收中断。因为发送字符串时我们是知道什么时候需要发送的,也就是说可以不归结为紧急事件,所以一般不用发送中断 _EINT(); } //************************************************* // function : UART_Send_Char // parameter : data (待发送的数据) // description : UART发送一字节数据 //************************************************* void UART_Send_Char(uchar data) { TXBUF0 = data; while (!(IFG1 & UTXIFG0)); } //************************************************* // function : UART_Rev_Char // parameter : data (待发送的数据) // description : UART接收一字节数据 //************************************************* uchar UART_Rev_Char(void) { return (RXBUF0); } //************************************************* // function : UART_Send_String // parameter : data (待发送的数据) // description : UART发送一行字符串,我们默认为字符串以“#”作为结束符,不再以‘\0’作为结束符了,最后额外再发送换行符"\r\n" //************************************************* void UART_Send_String(uchar *txbuf,uint num) { uint count = num; while(count!=0) { UART_Send_Char(*txbuf++); count--; } LCD1602_Show(txbuf,num); UART_Send_Char('\r'); UART_Send_Char('\n'); } //************************************************* // function : UART0_RXISR // parameter : (无) // description : UART0的接收中断服务函数 //************************************************* #pragma vector=UART0RX_VECTOR __interrupt void UART0_RXISR(void) { if((U0RCTL & RXERR)==0) //确保当前不是传输错误中断 { IFG1 &= 0xbf; //清除UART0接收中断标志位 UART_Rev_String[rev_string_count] = UART_Rev_Char(); UART_Send_Char(UART_Rev_String[rev_string_count]); //串口回显。 if(UART_Rev_String[rev_string_count]=='#') //如果接收到‘#’,则代表字符串接收完毕,将rev_string_count清零,以待下一次接收字符串 { rev_string_count = 0; rev_string_complete = 1; } else { rev_string_count++; //接收一个字符后,rev_string_count自加,指向指针的下一个区域以待接收下一字节 rev_string_complete = 0; } } else { U0RCTL &= ~(FE + OE + BRK); } } // ================================================================== // DAC相关函数(SPI) // ================================================================== /********************************************************* * SPI控制DA(TLC5620)同步通信 * * SPI三线主模式 * * 硬件连接图 * * P5.0----STE1----DA LOAD * * P5.1----SIMO1----DA DATA * * P5.2----SOMI1----DA LDAC * * P5.3----UCLK1----DA CLK * * 采用的是: * Figure 3. Load-Controlled Update Using 8-Bit Serial Word (LDAC = Low) A1=0 A0=0 RNG=0 *********************************************************/ void TLC5620_Init(void) { P5SEL = 0x0a; //P5.1/5.3 用于spi模式 P5DIR |=0x0f; //P5.0~P5.3为输出 U1CTL = CHAR + SYNC+MM + SWRST; //CHAR:字符长度为1 //SYNC:SPI模式 //MM:主机模式 //SWRST:控制位 U1TCTL = CKPH+ SSEL0 + STC; //CKPL:时钟相位控制位:1:下降沿输出;0:上升沿输入 //SSEL1:时钟源选择位 //STC:从机发送控制位 spi三线模式 U1BR0 = 0x02; //波特率选择寄存器0 U1BR1 = 0x00; //波特率选择寄存器1 U1MCTL = 0x00; //The modulation control register is not used for SPI mode and should be set to 000h. ME2 |= USPIE1; //模块使能 U1CTL&=~SWRST; //开启SPI P5OUT |=BIT0+BIT2; //P5.0 P5.2 拉高 P5OUT ^=0x04; //P5.2 拉低 } void TLC5620_delay(void) { unsigned int i; for(i=0; i<50; i++); } void update_TLC5620(void) { //P5OUT &= ~(1<<0); // LOAD = 0 //TLC5620_delay(); //P5OUT |= (1<<0); // LOAD = 1 //TLC5620_delay(); //P5OUT &=~(1<<2); // LDAC = 0 //TLC5620_delay(); //P5OUT |= (1<<2); // LDAC = 1 //TLC5620_delay(); P5OUT ^=0x01; //P5.0 拉低 P5OUT |=BIT0; //P5.0 拉高 } void TLC5620_Convert(unsigned char data) { U1TXBUF = data; while((IFG2&UTXIFG1)==0); //USART1发送数据是否准备好 update_TLC5620(); } // ================================================================== // ADC12相关函数 // ================================================================== //将P6.0口输入的模拟电压AD转换后,用数码管输出。 //使用AD单通道多次转换,采集P6.0输入的模拟电压值(变化范围:0~3.3V),转换为数字量。 //建立二维数组和通过顺序查表的方法得出采集回来的电压值。然后通过数码管显示当前电压值,显 //示跟随输入的模拟电压的变化。由于只有两位数码管,故显示电压值精确到小数点后一位,如当前 //输入电压2.37V,则显示2.4V。 //************************************************* // function : ADC12_Init // parameter : (无) // description : ADC12初始化 //************************************************* void ADC12_Init(void) //初始化函数 { WDTCTL = WDTPW+WDTHOLD; //关看门狗 P6SEL |= 0x01; // 设置P6口的P6.0引脚为外围模块AD转换器的模拟信号输入引脚ADC12CTL0 &= ~ENC; //复位转换允许位 ADC12CTL0 = ADC12ON + SHT0_2 + REFON + REF2_5V; //ADC12内核工作,采样周期4×tADC12CLK×4 //内部参考电压打开,内部参考电压发生器的电压为2.5V ADC12CTL1 = SHP + CONSEQ_2 ; // SHP:SAMPON来自采样定时器,采样信号上升沿触发采样 //CONSEQ_2=2*2 设置工作模式为单通道、多次转换模式 ADC12MCTL0 = SREF_0; //选择参考电压为VR+=AVCC,VR-=AVSS ,因此输入模拟信号范围是3.3V~0V。 ADC12IE |= BIT0; //使通道A0转换后产生中断 } //************************************************* // function : ADC12 // parameter : (无) // description : ADC12模数转换 //************************************************* void ADC12(void) { ADC12_Init(); //调用初始化函数 _EINT(); //使能中断 ADC12CTL0 |= ENC+ADC12SC; //置位换允许位 while (1); //无限次的while循环 } //************************************************* // function : ADC12ISR // parameter : (无) // description : ADC12模数转换中断 //************************************************* #pragma vector=ADC_VECTOR __interrupt void ADC12ISR (void) //AD转换中断函数 { unsigned int Table[4][10] = { {0x040,0x0BC,0x138,0x1B4,0x230, 0x2AC , 0x328 , 0x3A4 , 0x420 ,0x49C }, { 0x518 , 0x594 , 0x610 , 0x68C , 0x708 , 0x784 , 0x800, 0x87C , 0x8F8,0x974 }, { 0x9F0 , 0xA6C , 0xAE8 , 0xB64 , 0xBE0 , 0xC5C , 0xC08 , 0xD54 , 0xDD0,0xE4C }, { 0xEC8 , 0xF44 , 0xFC0 , 0xFFF } }; //该数组元素用于与AD转换的电压数值相比较,如果某个数组元素稍大于等于AD转换后的电压数 //值,则将此元素输出 unsigned char seg_7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //声明无小数点显示的数码管七段字型码数组 unsigned char seg_8[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //声明有小数点显示的数码管七段字型码数组 SEG_Init(); unsigned i,j; ADC12CTL0 &= ~ENC; //停止AD转换 for ( i=0 ; i<4 ;i++) //扫描Table 数组行下标 { for (j=0; j<10; j++) //扫描Table 数组列下标 { if (ADC12MEM0<=Table[i][j]) goto xxx; //如果Table数组元素大于转换数值,则转到标号xxx } } xxx: { SEG_Show(0,seg_7[j]); //数码管0显示十分位 SEG_Show(1,seg_8[i]); //数码管1显示个位和小数点 } ADC12CTL0 |= ENC+ADC12SC;// 使能再次转换 } // ================================================================== // 主函数 // ================================================================== void main(void) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 while(1){} } MSP430定位数据或函数 2010-12-29 13:51 在IAR环境中实现数据或函数的定位! -------------------------------------------------------------------------------- 注意:在实现过程中可能涉及到.XCL连接文件的更改,请保存好原来的.XCL文件! 1.打开相应的*c.xcl文件,用"-Z(CONST)段名=程序定位的目标段-FFDF"定义段的起始地址. 2.在自己的C程序中用#pragma constseg(段名)定位自己的程序 3.结束后恢复编译器的默认定位#pragma default IAR 1.26b环境下: 1、将常量数组放在FLASH段自定议的MYSEG段中 原来的MSP430F149 XCL文件如下: // Constant data -Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=1100-FFDF 如果想从中分出一部分做数据存储区,做如下修改: -Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=1500-FFDF //将1100-14FF 从ROM中分出存储arry数组 -Z(CONST)MYSEG=1100-14FF 区间大小可自行决定 在程序中描写如下即可: #pragma memory = constseg(MYSEG) //在.XCL文件中修改 /******************************************************** * 文件名称: * IIC.c * 文件说明: * 使用口线模拟IIC * 程序使用波特率为2400,程序运行时需要在pc机上使用一个串口* 接收发送程序,任意发送字符,接收的字符为十六进制时间数据* MSP-FET430P149 Demo - Basic Clock, MCLK Sourced from HF XTAL XT2 * L.TCH * Feb 2007 * Built with IAR Embedded Workbench Version: 3.10A *******************************************************/ /*********************************************************/ #include /*****用串口助手发什么回复什么****/ #include "" // ACLK = REFO = 32768Hz, MCLK = SMCLK = default DCO/2 = 1048576Hz // ,5——USCI_A0 TXD/RXD;,5——USCI_A2 TXD/RXD;,5——USCI_A3 TXD/RXD; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P4SEL |=BIT4+BIT5 ; // ,7 = USCI_A1 TXD/RXD UCA1CTL1 |= UCSWRST; // **Put state machine in reset** UCA1CTL1 |= UCSSEL_2; // SMCLK UCA1BR0 = 9; // 1MHz 115200 (see User's Guide) UCA1BR1 = 0; // 1MHz 115200 UCA1MCTL |= UCBRS_1 + UCBRF_0; // Modulation UCBRSx=1, UCBRFx=0 UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA1IE |= UCRXIE; // Enable USCI_A1 RX interrupt __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled } // Echo back RXed character, confirm TX buffer is ready first,发送数据之前确定发送缓存准备好 #pragma vector=USCI_A1_VECTOR __interrupt void USCI_A1_ISR(void) { switch(__even_in_range(UCA1IV,4)) { case 0:break; // Vector 0 - no interrupt case 2: // Vector 2 - RXIFG while (!(UCA1IFG&UCTXIFG)); // USCI_A1 TX buffer ready UCTXIFG(USCI Transmit Interrupt Flag) //等待数据发送完成完成UCTXIFG置1 跳出循环 UCA1TXBUF = UCA1RXBUF; // TX -> RXed character break; case 4:break; // Vector 4 - TXIFG default: break; } } // UCTXIFG=0x02,UCA1IFG&UCTXIFG,当UCA1IFG的UCTXIFG位为1时,说明UCA1TXBUF 为空, //跳出while循环循环;当UCTXIFG位为0时UCA1TXBUF不为空,停在循环。 #include #include "io430.h" #include "in430.h" #include "shumaguan.h" void UartPutchar(unsigned char c); unsigned char UartGetchar(); unsigned char temp=0; unsigned char number[2]={0}; void main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ; P1DIR|=BIT6; P1OUT&=~BIT6; P1SEL = BIT1 + BIT2; // P1.1为RXD, P1.2为TXD P1SEL2 = BIT1 + BIT2; // P1.1为RXD, P1.2为TXD UCA0CTL1 |= UCSSEL_2; // 选择时钟BRCLK UCA0BR0 = 106; // 1MHz 9600 UCA0BR1 = 0; // 1MHz 9600 UCA0MCTL = UCBRS2 + UCBRS0; // 波特率=BRCLK/(UBR+(M7+...0)/8) UCA0CTL1 &= ~UCSWRST; // 初始化顺序:SWRST=1设置串口,然后设置SWRST=0,最后设置相应中断 IE2 |= UCA0RXIE; // 使能接收中断 while(1) { //UartPutchar(9); display_int(temp,0); delay(); } } /**********************************UART接收中断********************************/ #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR(void) { //while (!(IFG2&UCA0TXIFG)); // 等待发送完成 串行通信接口是处理器与外界进行数据传输最常用的方式之一。顾名思义,串行通信是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。与并行通信相比,串行通信速度较慢,但占用更少的I/O 资源,只需要少数几条线就可以在系统间交换信息,特别适用于计算机与计算机、计算机与外设之间的远距离通信。 串行通信可以分为同步通信和异步通信两种类型。如果带有同步时钟,则称为同步串行 通信,如常用的 SPI 和 I2C 接口就属于同步串行通信接口。如果没有同步时钟,依靠严格的时间间隔来传输每一比特,则称为异步串行通信。MSP430 系列单片机有两种串行通信接口,较早的 USART 模块和较新的 USCI 模块。 同步通信方式,是把许多字符组成一个信息组,这样,字符可以一个接一个地传输。但是,在每组信息(通常称为信息帧)的开始要加上同步字符,在没有信息要传输时,要填上空字符,因为同步传输不允许有间隙。同步方式下,发送方除了发送数据,还要传输同步时钟信号,信息传输的双方用同一个时钟信号确定传输过程中每1位的位置。 在异步通信方式中,两个数据字符之间的传输间隔是任意的,所以,每个数据字符的前后都要用一些数位来作为分隔位。 MSP430G2553单片机USCI模块原理图 串口通信所需配置: 1、时钟选择——以SMCLK时钟频率为1MHz为例。 ①选择SMCLK为串口通信频率。(P95页) ②设置SMCLK时钟频率为1MHz。 需要设置的寄存器:UCA0CTL1;(P95页)。 2、IO口定义为第二功能,即串口发送接收端口。 需要设置的寄存器:P1SEL|=BIT1+BIT2;,P1SEL2|=BIT1+BIT2;(中文P44页)。 2、数据传输格式 摘要:介绍了一种MSP430单片机通过串口升级程序的方法,并在MSP430F5438上得以实现。通过实验,证明此方法稳定、可靠,避免了利用仿真器更新程序的 繁琐,提高了效率。 关键词:MSP430F5438;串口;程序更新 随着性能的不断提高以及成本的降低,单片机在各个领域都得到了广泛的应用。尤其在信号的控制和处理方面,单片机以其超低的功耗、简单的操作成为设计者的首选。TI公司推出的MSP430x5xx系列单片机具有低电压、低功耗、高速处理能力以及配置灵活的接口等特点,是当今主流单片机之一。 同其他处理器一样,单片机正常工作除了需要硬件电路以外,还需要相应的用户应用程序。但应用程序在调试阶段以及实际使用时往往都需要更新,常规的方法需要打开机箱,将仿真器与单片机连接好,再更新程序。这种步骤比较繁琐,如果操作不当还会损坏设备。因此,如果能通过单片机已有的简单接口(如串口)更新应用程序,那么将给单片机的使用带来更大的方便。 1 总体思想 首先通过仿真器向单片机中写入一段小程序,称之为Bootloader程序。这个程序不是用户的应用程序,它的作用有两个:第一是在上电的一小段时间里实时检测串口,如果有上位机发出的更新程序命令,就发送握手信号,通知上位机发送更新代码,并将收到的更新代码写入单片机相应的Flash中;第二个作用是当检测到有应用程序存在时,跳转到应用程序的入口地址,执行应用程序。其流 程如图1所示。 上位机程序(VC++语言编写)的功能是,当用户发出更新程序的指令后,在一段时间内连续发送更新程序命令。如果收到单片机的应答信号,表示单片机准备开始接收更新代码。此时上位机读取已选择的代码文件,分段发给单片机。其流程如 MSP430g2553串口通信 MSP430的不同型号,其串行通讯工作模式是一样的。以MSP430G2553为例进行说明。MSP430G2553是20个引脚的16位单片机。具有内置的16位定时器、16k 的FLASH 和512B 的RAM ,以及一个通用型模拟比较器以及采用通用串行通信接口的内置通信能力。此外还具有一个10位的模数(A/D)转换器。其引脚排布如图1.1所示。其功能表如表1.1所示。 串行通讯模块主要由三个部分组成:波特率生成部分、发送控制器以及接收控制器。如图1.2所示。 一、UART 模式 在异步模式下,接收器自身实现帧的同步,外部的通讯设备并不使用这一时钟。波特率的产生是在本地完成的。异步帧格式由1个起始 位、7或8个数据位、校验位(奇/偶/无)、1个地址位、和1或2个停止位。一般最小帧为9个位,最大为13位。 图1.2 串行通讯模块内部结构图 图1.1 MSP430G2553引脚图 (一)UART的初始化 单片机工作的时钟源来自内部三个时钟或者外部输入时钟,由SSEL1、SSEL0,以决定最终进入模块的时钟信号BRCLK的频率。所以配置串行通讯的第一步就是选择时钟。 通过选择时钟源和波特率寄存器的数据来确定位周期。所以波特率的配置是串行通讯中最重要的一部分。波特率设置用三个寄存器实现:UxBR0(选择控制器0):波特率发生器分频系数低8位。UxBR1(选择控制器1):波特率发生器分频系数高8位。UxMCTL 数据传输的格式,以及数据传输的模式是通过配置控制寄存器UCTL来进行设置。 接收控制部分和发送控制部分。首先需要串行口进行配置、使能以及开启中断。串口接收数据一般采用中断方式,发送数据采用主动发送。当接收到一个完整的数据,产生一个信号:URXIFG0=1(类似于51单片机的接收中断标志位),表示接收完整的数据。当数据正在发送中,UTXIFG0=1,此时不能再发送数据,必须等当前数据发送完毕(UTXIFG0=0)才能进行发送。程序实例如下: Void UART_init() { WDTCTL = WDTPW + WDTHOLD; P1SEL|= 0x06;//I/O口的功能寄存器配置。为1时作为模块输出或者输出,0 为端口输入或者输出。配置P1.1,P1.2为串行口。 P2DIR=0x04;//串口发送端为输出,串口接收端为输入。0为输入,1为输出 U0CTL |= CHAR; // 配置控制寄存器,数据类型为8位。 U0TCTL |= SSEL0; // 选择时钟UCLK= ACLK。 U0BR0 = 0x45; // 分频系数的高8位,8MHz 时钟下波特率为115200 U0BR1 = 0x00; // 分频系数的低8位。 U0MCTL = 0x00; // 波特率的调整。 U0CTL&= ~SWRST;//系统复位。只有对SWRST 复位,USART 才能重新被允许。 而接收和发送允许标志URXE和UTXE不会因SWRST 而 更改。 ME1 |= UTXE0 + URXE0; //使能USART0 TXD/RXD模块USART中特有的使能配置。 IE1 |= URXIE0;//使能USART0 接收中断 _EINT();//开启全部中断。 _BIS_SR(LPM0_bits + GIE); // 初始化完毕,进入睡眠状态。等待工作。该程序直接调用。 } 发送数据函数: __interrupt void usart0_rx (void) { while (!(IFG1 & UTXIFG0)); // 判断发送缓冲区是否为空。 TXBUF0 = RXBUF0; // 将数据发送到串口。 } #ifndef __sm_uart__ #define __sm_uart__ #endif #include "stdio.h" #define uart_rate 115200 #define MaxLenStr 100 #define uart_buf_tx_size 100 #define uart_buf_rx_size 100 #define MCLK_rate 1000000 //#define CH_TAB_OT //------------- char uart_rx_buf[uart_buf_rx_size]; char *inRxBuf = uart_rx_buf; char *outRxBuf = uart_rx_buf; //------------- char uart_tx_buf[uart_buf_tx_size]; char *inTxBuf =uart_tx_buf; char *outTxBuf =uart_tx_buf; u16 TIflag=1;//Note:It must be 1. /*---------------------------------------------------------------------*/ #ifndef uart_rate void init_uart(void) { P3SEL |= 0x30; // 3.4 3.5 USART0 TXD/RXD ME1 |= UTXE0 + URXE0; // Enabled USART0 TXD/RXD UCTL0 |= CHAR; // 8-bit character, SWRST=1 #if ENABLE_PENA UCTL0 |=PENA; //允许校验 #endif UTCTL0 |= SSEL0; // UCLK = Uclki UBR00 = 0x03; //L UBR10 = 0x00; //H UMCTL0 = 0x4a; // Modulation UCTL0 &= ~SWRST; // Initialize USART state machine IE1 |= URXIE0 + UTXIE0; // Enable USART0 RX/TX interrupt IFG1 &= ~UTXIFG0; // Clear inital flag on POR } #else //------------------------------------------- void init_uart(void) { P3SEL |= 0x30; // 3.4 3.5 = USART0 TXD/RXD ME1 |= UTXE0 + URXE0; // Enabled USART0 TXD/RXD UCTL0 |= CHAR; // 8-bit character, SWRST=1 MSP430单片机串口通信详解 #include"msp430G2553.h" #include "in430.h" void UartPutchar(unsigned char c); unsigned char UartGetchar(); unsigned char temp=0; unsigned char number[2]={0}; void main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_1MHZ; // Set DCO DCOCTL = CALDCO_1MHZ; P1DIR|=BIT6; P1OUT&=~BIT6; P1SEL = BIT1 + BIT2; // P1.1为 RXD, P1.2为TXD P1SEL2 = BIT1 + BIT2; // P1.1为 RXD, P1.2为TXD UCA0CTL1 |= UCSSEL_2; // 选择时钟BRCLK UCA0BR0 = 106; // 1MHz 9600 UCA0BR1 = 0; // 1MHz 9600 UCA0MCTL = UCBRS2 + UCBRS0; // 波特率 =BRCLK/(UBR+(M7+...0)/8) UCA0CTL1 &= ~UCSWRST; // 初始化顺序:SWRST=1设置串口,然后设置SWRST=0,最后设置相应中断 IE2 |= UCA0RXIE; // 使能接收中断 while(1) { //UartPutchar(9); // display_int(temp,0); __delay_cycles(10000); } } /**********************************UART接收中断*************************/ #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR(void) { //while (!(IFG2&UCA0TXIFG)); // 等待发送完成 //UCA0TXBUF = UCA0RXBUF; // TX ->; RXed character temp=UCA0RXBUF; } /*main.c ******************************************************************************* 功能:串口通信 日期:2013.9.11 姓名:MRT notice:无论接收发送只要标志位(TI RI)置位立马进入中断一般情况即使中断 不允许的情况下buffer中任然接收到数据并存储 ******************************************************************************* * **/ #include"msp430x14x.h" #include"whole.h" #include"main.h" struct power guss; unsigned char buffer_value; void main() { WDTCTL = WDTPW + WDTHOLD; init_usart(); init_clk(); _EINT(); while(1) { } } #pragma vector = USART0RX_VECTOR __interrupt void usart0_rx(void) { buffer_value++; guss.buffer[0] = RXBUF0; if(buffer_value==1) { guss.buffer[1] = RXBUF0; guss.value = guss.buffer[1]; guss.value<<=4; } if(buffer_value==2) { guss.buffer[2] = RXBUF0; buffer_value = 0; } } msp430串口接收函数 篇一:基于msp430串口接收中断 #include void main { WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1SEL |= BIT1 + BIT2; P1SEL2 |= BIT1 + BIT2;//需要对照着手册来看UCA0CTL1 |= UCSSEL_2;//选择串口的校验位 UCA0BR0 = 104;//9600 波特率的计算一般都存在误差 UCA0BR1 = 0; UCA0MCTL = UCBRS0;//校准波特率用所以要使用校准UCA0CTL1 &= ~UCSWRST;//让串口进行复位 IE2 |= UCA0RXIE;//开启接收中断 __bis_SR_register; } #pragma vector = USCIAB0RX_VECTOR __interrupt void USART_RECEIVE { UCA0TXBUF = UCA0RXBUF+1; while);//等待发送完毕可加可不加 } 篇二:MSP430串口收发程序 MSP430 标准库printf函数实现 20XX-08-02 21:22 关键是增加一个putchar函数。 代码如下: #include #include void NOP10 { _NOP ; _NOP ; _NOP ; _NOP ; _NOP ; _NOP ; _NOP ; _NOP ; _NOP ; _NOP ; } int putchar//注意不要改参数的类型和返回值的类型,否则printf调用是就有问题了。 #include MSP430单片机串口的程序升级方法 摘要:介绍了一种MSP430单片机通过串口升级程序的方法,并在MSP430F5438上得以实现。通过实验,证明此方法稳定、可靠,避免了利用仿真器更新程序的繁琐,提高了效率。关键词:MSP430F5438;串口;程序更新随着性能的不断提高以及成本的降低,单片机在各个领域都得到了广泛的应用。尤其在信号的控制和处理方面,单片机以其超低的功耗、简单的操作成为设计者的首选。TI公司推出的MSP430x5xx系列单片机具有低电压、低功耗、高速处理能力以及配置灵活的接口等特点,是当今主流单片机之一。同其他处理器一样,单片机正常工作除了需要硬件电路以外,还需要相应的用户应用程序。但应用程序在调试阶段以及实际使用时往往都需要更新,常规的方法需要打开机箱,将仿真器与单片机连接好,再更新程序。这种步骤比较繁琐,如果操作不当还会损坏设备。因此,如果能通过单片机已有的简单接口(如串口)更新应用程序,那么将给单片机的使用带来更大的方便。1 总体思想首先通过仿真器向单片机中写入一段小程序,称之为Bootloader程序。这个程序不是用户的应用程序,它的作用有两个:第一是在上电的一小段时间里实时检测串口,如果有上位机发出的更新程序命令,就发送握手信号,通知上位机发送更新代码,并将收到的更新代码写入单片机相应的Flash中;第二个作用是当检测到有应用程序存在时,跳转到应用程序的入口地址,执行应用程序。其流程。 上位机程序(VC++语言编写)的功能是,当用户发出更新程序的指令后,在一段时间内连续发送更新程序命令。如果收到单片机的应答信号,表示单片机准备开始接收更新代码。此时上位机读取已选择的代码文件,分段发给单片机。其流程。2 相关知识2.1 IAR设置常用的MSP430单片机软件开发环境是IAR C/C++Compiler for MSP430。用仿真器进行程序烧写以及仿真调试时,在Options→Linker→ Output→Format选项中选择的是“Debug information for C-SPY”,但如果要得到该程序文本格式的代码文件,需要选择Format中的Other选项。2.2 代码文件格式下面是一个生成的txt文件的内容: @后面的6C00表示起始地址,接下来的内容需要依次写入6C00开始的地址中。@FCFF表示程序的复位入口地址,单片机上电或者复位后,程序从这里开始运行。最末行q 表示结束。2.3 xcl文件上面生成的txt文件中的代码存放地址、复位入口地址以及中断入口地址都可以通过配置文件进行修改,这个文件就是xcl文件。该文件在安装目录的IAR Systems\Embedded Workbench 5.4 Evaluation\430\config中,本文所使用的单片机对应的配置文件是lnk430F543 8.xcl,将其复制到自己创建的工程中以便修改。在编译器的Options→Linker→Config→Linker command file选项中指定这个配置文件。下面是xcl文件中的部分内容:上面的配置信息含义是代码(Code)和数据常量(Constant data)放在5C00~FF7F和10000~45BFF两个空间中。中断向量的地址是FF80~FFFF,其中复位向量的地址是FFFE~FFFF。2.4 Bootloader程序和用户应用程序的关系地址空间分配。图3左面是MSP430F5438的空间分配。在正常的使用中,用户代码占用5C00~FF7F、10000~45BFF两块区域,中断向量为FF80~FFFF。但含有Bootloader的程序,就与之有所区别了。即Bootloader程序占用了一部分代码区,同时占有中断向量FF80~FFFF。而用户需要重新编写一个中断向量表,以及相应的入口地址。图3右面是Bootloader程序和用户程序以及自定义的中断向量在Flash中的位置。关于空间位置以及空间大小可以根据实际情况进行调整。 从图中可以看出,在代码空间中存在着两个独立的程序:Bootloader程序和用户程序。Bootloader完成的功能是在复位时通过上位机更新用户程序或者调用已经存在的用户程序。 MSP430F5437通过串口向PC发送字符串,使字符串显示在串口助手中。单片机不停地发送字符,流程图如图所示。 程序代码如下: #include "msp430x54x.h" unsigned char buffer[] = {"I'm MSP430!\n"}; void delay(unsigned int n) { unsigned int i,j; for(i=0;i } void main(void) { unsigned int i; WDTCTL = WDTPW + WDTHOLD; // 关狗 P5SEL = 0xC0; // P5_6和P5_7第二功能打开,设置方向P5DIR = 0x40; UCA1CTL1 |= UCSWRST; // 首先使RST位置位,只有这样后面的设置才有效UCA1CTL1 |= UCSSEL_2; // SMCLK,为系统时钟1048576Hz UCA1BR0 = 9; // 1MHz 115200 UCA1BR1 = 0; // 1MHz 115200 UCA1MCTL |= UCBRS_1 + UCBRF_0; // 设置调整参数UCBRSx=1, UCBRFx=0 UCA1CTL1 &= ~UCSWRST; // RST复位 UCA1IE |= UCTXIE; // 使能发送中断允许 while(1) { while (!(UCA1IFG&UCTXIFG)); //等待BUF区准备好,当IFG=1时就表示准备好了for(i=0; i MSP430 标准库printf函数实现 2011-08-02 21:22 关键是增加一个putchar函数。 代码如下: #include UMCTL1 = 0x6B; // Modulation UCTL1 &= ~SWRST; // Initalize USART state machine IE2 |= URXIE1; // Enable USART1 RX interrupt //IFG2 |= UTXIFG1; } void main(void) { unsigned char i; i=0x10; WDTCTL = WDTPW + WDTHOLD; // Stop WDT FLL_CTL0 |= XCAP18PF; // Configure load caps InitalUart1(); _EINT(); // LPM0; while(1) { // while (!(IFG2 & UTXIFG1)); // USART1 TX buffer ready? // TXBUF1 = 'H'; //putchar(0x05); //putchar('c'); printf("%d",i); NOP10(); } } #pragma vector=USART1RX_VECTOR __interrupt void usart1_rx(void) { while (!(IFG2 & UTXIFG1)); // USART1 TX buffer ready? TXBUF1 = RXBUF1; // RXBUF1 to TXBUF0 //LPM0_EXIT; msp430各模块函数整合(1) 2010-08-13 14:27 /*************************************************** 程序功能:控制8个LED闪烁,用于测试下载功能是否正常 测试说明:观察LED闪烁 ***************************************************/ #include MSP430波特率的计算 给定一个BRCLK时钟源,波特率用来决定需要分频的因子N: N = fBRCLK/Baudrate 分频因子N通常是非整数值,因此至少一个分频器和一个调制阶段用来尽可能的接近N。 如果N等于或大于16,可以设置UCOS16选择oversampling baud Rate模式 注:Round():指四舍五入。 Low-Frequency Baud Rate Mode Setting 在low-frequency mode,整数部分的因子可以由预分频实现: UCBRx = INT(N) 小数部分的因子可以用下列标称公式通过调制器实现: UCBRSx = round( ( N –INT(N) ) × 8 ) 增加或减少UCBRSx一个计数设置,对于任何给定的位可能得到一个较低的最高比特误码率。如果确定是这样的情况UCBRSx设置的每一位必须执行一个精确的错误计算。 例1:1048576Hz频率下驱动以115200波特率异步通讯 ACLK = REFO = ~32768Hz, MCLK = SMCLK = default DCO = 32 x ACLK = 1048576Hz。 N = fBRCLK/Baudrate = 1048576/115200 = ~9.10 UCBRx = INT(N) = INT(9.10) = 9 UCBRSx = round( ( N –INT(N) )×8 ) = round( ( 9.10 –9) × 8 )=round(0.8 )=1 UCA0CTL1 |= UCSSEL_2;// 选SMCLK为时钟 UCAxBR0 = 9; UCAxBR1 = 0; UCAxMCTL = 0x02;//7-4:UCBRFx,3-1:UCBRSx,0:UCOS16 UCBRSx 为寄存器UCAxMCTL的1-3位,所以写入0x02(00000010) 例2:32768Hz频率下驱动以2400波特率异步通ACLK = REFO = ~32768Hz, MCLK = SMCLK = DCO ~1.045MHz N = fBRCLK/Baudrate = 32768/2400 = ~13.65 UCBRx = INT(N) = INT(13.65) = 13 UCBRSx = round( ( N –INT(N) )×8 ) = round( ( 13.65 –13) × 8 )=round(5.2)=5 UCA0CTL1 |= UCSSEL_1; // 选ACLK为时钟 UCAxBR0 = 13;UCAxBR1 = 0 ; UCAxMCTL = 0x0A;//7-4:UCBRFx,3-1:UCBRSx,0:UCOS16 UCBRSx为寄存器UCAxMCTL的1-3位,所以写入0x0A(00001010) Oversampling Baud Rate Mode Setting单片机MSP430F149-DS1302读写及串口收发程序
msp430f5529简单uart程序
msp430串口1收发程序
串口通信UART(msp430g2553)
MSP430串口通信讲解
430单片机串口的程序升级
MSP430g2553串口通信
msp430串口带缓存printf代码
MSP430单片机串口通信详解
MSP430单片机串口通信实例(已验证)
msp430串口接收函数
msp430AD采样并串口发送
MSP430单片机串口的程序升级方法
MSP430f5437uart串口总结
MSP430串口收发程序
MSP430串口波特率的设置与计算