TimerA模拟Uart,接收不正确
芯片型号是Msp430F4250参考一些样例程序做了个模拟Uart,现在调试时发现接收不正确(发送还未调试),具体来说:用串口调试软件发送几字节数据,然后用仿真器设置断点,查看接收数据是否正确。波特率定为9600。每次接收的数据只有第一个字节正确,后面全错;发送字节数超过三个时,接收字节数也不正确,比如发送8个字节,程序中显示收到6个字节。主要程序如下:
程序的大体思路:用TimerA 的 CCR0收发数据 用CCR1作接收超时判断(长时间没有收到数据时,认为数据接收完毕,开始处理数据)
单字节接收缓存到变量intData,每接收完一字节,存放到uchRcvBuf[]数组中,变量uchMsgLen指示已经接收的字节数
今天弄了一天也没有进展,缺失方向。恳请大家帮忙!
#define Bitime_5 0x30 //半位时长
#define Bitime 0x6C //一位时长
//------------------------------------------------------------------------------
// Timer_A CCR0中断服务函数
// 用于UART功能
//
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA_CCR0_ISR(void)
{
CCR0 += Bitime;
//CCTL0&=~CCIFG;
if(CCTL0 & CCIS0) //-----逐位接收-----------------------------------------
{
if(CCTL0 & CAP ) // Capture mode = start bit edge
{
CCTL0 &= ~ CAP; // Capture to compare mode
CCR0 += Bitime_5;
CCTL1=0x0; // 停止接收超时检查
}
else
{
intData=intData>>1;
if(CCTL0 & SCCI) intData|=0x80; // Get bit waiting in receive latch
uchBitCnt--; // All bits RXed?
if(uchBitCnt==0)
{
uchRcvBuf=(unsigned char)intData; //保存数据
uchMsgLen=(uchMsgLen+1)%cst_MaxMsgLen; //
uchBitCnt=8; //准备接收下一字节
//CCTL0|=CAP; //恢复为捕获模式
CCTL0 = SCS + CCIS0 + OUTMOD0 + CM1 + CAP + CCIE;// Sync, Neg Edge, Capture
TACCR1=TAR+Bitime*50; //设置CCR1,定时4个字节的传输时间
CCTL1=CCIE; //启用CCR1中断
}
}
}
else //-----逐位发送-----------------------------------------
{
if(uchBitCnt==0)
CCTL0&=~CCIE;
else
{
if (intData & 0x01)
CCTL0 &= ~ OUTMOD2; //输出1
else
CCTL0|=OUTMOD2; //输出0
intData=intData>>1;
uchBitCnt--;
}
}
}
//******************************************************************************
// Timer_A CCR1\CCR2\TA中断服务
// 睡眠唤醒
//
#pragma vector=TIMERA1_VECTOR
__interrupt void TimerA_CCR1_ISR(void)
{
switch(__even_in_range(TAIV,4))
{
case 2: //CCR1中断---------------------------------------------串口等待
CCTL0=0; //
CCTL1=0; //
UART_ISR(uchRcvBuf,uchMsgLen); //处理串口消息------在此处设置断点,查看接收到的数据
uchMsgLen=0;
uchBitCnt=8; //恢复TimerA CCR0设置(接收功能)
CCTL0=SCS+CCIS0+OUTMOD0+CM1+CAP+CCIE; // Sync, Neg Edge, Capture
break;
case 10: //TA中断-----------------------------------------------睡眠唤醒
TACTL=0x0;
__low_power_mode_off_on_exit();
}
} 我以前写的/*
* 看了很久才发现这个是软件
* 模拟UART.所以用不到UART
* 控制器.基本思想是定时器根据
* 波特率来产生中断,每次中断的
* 时候I/O根据发送内容来翻转.
*/
#include<msp430.h>
#define RED_LED BIT0
#define GRN_LED BIT6
#define BUTTON BIT3
#define TXD BIT1
#define RXD BIT2
/*
* 2400 bps -> 52
*/
#define TPB 52
int TXWord;
unsigned char bitcnt = 0;
void inituart(void);
void sendbyte(unsigned char b);
void sendstring( const char *str);
void main(void)
{
/*关闭看门狗*/
WDTCTL = WDTPW + WDTHOLD;
/*LED设置为输出模式*/
P1DIR |= RED_LED + GRN_LED;
P1OUT &= ~(RED_LED + GRN_LED);
/*初始化UART*/
inituart();
/*
* 初始化按键
* 输入模式
*/
P1DIR &= ~BUTTON;
/*中断标志清零*/
P1IFG &= ~BUTTON;
/*中断标志使能*/
P1IE |= BUTTON;
for(;;)
{
/*全局中断开,进入低功耗模式LPM3*/
_BIS_SR(LPM3_bits + GIE);
/*发送字符串*/
sendstring("XIAO JB\r\n");
}
}
void inituart(void)
{
/*I/O初始化*/
P1OUT |= TXD;
P1DIR |= TXD;
/*时钟初始化*/
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
/*SMCLK4分频,SMCLK=1000KHz/4=500KHz*/
BCSCTL2 &= ~(DIVS_3);
/*定时器初始化,SMCLK,向上计数,500KHz/8=62.5KHz,计数器清零*/
TACTL = TASSEL_2 + MC_1 + ID_3 + TACLR;
TACCR0 = TPB;
}
void sendbyte(unsignedchar b)
{
TXWord = b;
TXWord |= 0x100;
TXWord <<= 1;
bitcnt = 10;
/*清零计数器*/
TACTL |= TACLR;
/*清零中断标志位*/
TACCTL0 &= ~CCIFG;
/*中断使能*/
TACCTL0 |= CCIE;
/*等待中断发生*/
while(TACCTL0 & CCIE)
{
_BIS_SR(LPM0_bits + GIE);
}
}
/*发送一个字符串*/
void sendstring(const char *str)
{
char *c = str;
for(; *c; c++)
{
sendbyte(*c);
}
}
/*定时器中断函数声明*/
void TimerA0(void) __attribute__((interrupt(TIMER0_A0_VECTOR)));
void TimerA0(void)
{
/*中断标志位清零*/
TACCTL0 &= ~CCIFG;
/*如果位计数器为零,发送完毕,返回*/
if(!bitcnt)
{
TACCTL0 &= ~CCIE;
__bic_SR_register_on_exit(LPM0_bits);
return;
}
else
{
/*判断要发送的字节的第一位*/
if(TXWord & 0x01)
{
P1OUT |= TXD;
P1OUT |= RED_LED;
P1OUT &= ~GRN_LED;
}
else
{
P1OUT &= ~TXD;
P1OUT |= GRN_LED;
P1OUT &= ~RED_LED;
}
/*左移,继续发送,直至bitcnt==0*/
TXWord >>= 1;
bitcnt --;
}
}
/*按键中断函数声明*/
void Port_1(void) __attribute__((interrupt(PORT1_VECTOR)));
void Port_1(void)
{
/*清零中断标志位*/
P1IFG &= ~BUTTON;
/*退出低功耗模式LPM3*/
__bic_SR_register_on_exit(LPM3_bits);
} 笑笑我笑了 发表于 2013-9-24 20:36 static/image/common/back.gif
我以前写的
这是模拟发送,有接收部分吗? 接收结束的时候判断1.5个停止位就可以了!你上BAIDU文库搜搜把! activeleo 发表于 2013-9-24 22:09 static/image/common/back.gif
接收结束的时候判断1.5个停止位就可以了!你上BAIDU文库搜搜把!
百度文库没有找到有用的信息,也偿试了接收停止位(在收到第8位数据后,又执行了一个1.5位的等待--通过定时器的比较模式实现),情况与之前一模一样。 接收已经正常了,呵呵,心情不错。原因是主系统时钟频率比较低,中断处理程序的运行时间稍长,再次打开捕获时,错过了正确的起始位。 波特率降到2400,或者仍然使用9600,但是发送采用两个停止位,这两种方式都正确接收数据。 //******************************************************************************
//MSP430F20xx Demo - Timer_A, Ultra-Low Pwr UART 2400 Echo, 32kHz ACLK
//
//Description: Use Timer_A CCR0 hardware output modes and SCCI data latch
//to implement UART function @ 2400 baud. Software does not directly read and
//write to RX and TX pins, instead proper use of output modes and SCCI data
//latch are demonstrated. Use of these hardware features eliminates ISR
//latency effects as hardware insures that output and input bit latching and
//timing are perfectly synchronised with Timer_A regardless of other
//software activity. In the Mainloop the UART function readies the UART to
//receive one character and waits in LPM3 with all activity interrupt driven.
//After a character has been received, the UART receive function forces exit
//from LPM3 in the Mainloop which echo's back the received character.
//ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO
////* An external watch crystal is required on XIN XOUT for ACLK *//
//
// MSP430F20xx
// -----------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// | CCI0B/TXD/P1.5|-------->
// | | 2400 8N1
// | CCI0A/RXD/P1.1|<--------
//
#define RXD 0x02 // RXD on P1.1
#define TXD 0x20 // TXD on P1.5
// Conditions for 2400 Baud SW UART, ACLK = 32768
#define Bitime_50x06 // ~ 0.5 bit length + small adjustment
#define Bitime 0x0E // 427us bit length ~ 2341 baud
volatile unsigned int RXTXData;
volatile unsigned char BitCnt;
void TX_Byte (void);
void RX_Ready (void);
//M. Buccini / L. Westlund
//Texas Instruments Inc.
//October 2005
//Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.40A
//******************************************************************************
#include <msp430.h>
/* main.c */
#include <stdio.h>
#include "linkedlist.h"
void print_item(link p)
{
printf("%d\n", p->item);
}
int main (void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
CCTL0 = OUT; // TXD Idle as Mark
TACTL = TASSEL_1 + MC_2; // ACLK, continuous mode
P1SEL = TXD + RXD; //
P1DIR = TXD; //
P1DIR |= 0x01; // Set P1.0 to output direction
//LPM3;
// Mainloop
for (;;)
{
P1OUT ^= 0x01; // LED Flash
RX_Ready(); // UART ready to RX one Byte
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr until char RXed
TX_Byte(); // TX Back RXed Byte Received
link p = make_node(10);
insert(p);
p = make_node(5);
insert(p);
p = make_node(90);
insert(p);
p = search(5);
delete(p);
free_node(p);
traverse(print_item);
destroy();
p = make_node(100);
push(p);
p = make_node(200);
push(p);
p = make_node(250);
push(p);
while (p = pop())
{
print_item(p);
free_node(p);
}
}
}
// Function Transmits Character from RXTXData Buffer
void TX_Byte (void)
{
unsigned char Tar = 0; // Warning: undefined behavior: the order of volatile accesses is undefined in this statement
unsigned char Ccr = 0; //
BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
Tar = TAR;
Ccr = CCR0;
//while ( CCR0 != TAR ) // Prevent async capture
//CCR0 = TAR; // Current state of TA counter
while ( Ccr != Tar ) // Prevent async capture
CCR0 = TAR; // Current state of TA counter
CCR0 += Bitime; // Some time till first bit
RXTXData |= 0x100; // Add mark stop bit to RXTXData
RXTXData = RXTXData << 1; // Add space start bit
CCTL0 =CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle
while ( CCTL0 & CCIE ); // Wait for TX completion
}
// Function Readies UART to Receive Character into RXTXData Buffer
void RX_Ready (void)
{
BitCnt = 0x8; // Load Bit counter
CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge, Cap
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
CCR0 += Bitime; // Add Offset to CCR0
// TX
if (CCTL0 & CCIS0) // TX on CCI0B?
{
if ( BitCnt == 0)
CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt
else
{
CCTL0 |=OUTMOD2; // TX Space
if (RXTXData & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
RXTXData = RXTXData >> 1;
BitCnt --;
}
}
// RX
else
{
if( CCTL0 & CAP ) // Capture mode = start bit edge
{
CCTL0 &= ~ CAP; // Switch from capture to compare mode
CCR0 += Bitime_5;
}
else
{
RXTXData = RXTXData >> 1;
if (CCTL0 & SCCI) // Get bit waiting in receive latch
RXTXData |= 0x80;
BitCnt --; // All bits RXed?
if ( BitCnt == 0)
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
{
CCTL0 &= ~ CCIE; // All bits RXed, disable interrupt
_BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR)
}
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
}
/*------------------------------------------------------------------------------
if ((0x10 & P1IN)) P1OUT |= 0x01; // if P1.4 set, set P1.0
else P1OUT &= ~0x01; // else reset
------------------------------------------------------------------------------*/
页:
[1]