您的位置:首页 > 其它

MSP430F149和PC机串口通信问题

2010-08-24 10:05 197 查看
Code:

//******************************************************************************

#include "msp430x14x.h" // Standard Equations

typedef unsigned char uchar ;

typedef unsigned int uint ;

/*******************************************

functional module

*******************************************/

void delay_l(int q);

void ClockInit() ; //时钟初始化

void UartInit() ; //串口通信初始化函数

void SendDataToPC(uchar *value) ; //发送数据函数

void SendDataToPC1(uchar value) ;

void ADDataTodecimal(uchar *p,uint value) ; //十六进制转换十进制函数

uchar value[5] ; //用来存放把一个十六进制熟转换为十

uint temp = 0 ; //Function as exchange data

uchar i,j ;

/********************************************

main function

********************************************/

void main(void)

{

WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer

value[4] = '/0' ; // ADD A END SIGN TO

ClockInit();

UartInit(); //Initial series communication

P6SEL |= 0x10 ; // Enable A/D channel A3

ADC12CTL0 = ADC12ON |REFON |REF2_5V ; // Turn on ADC12, set sampling time

ADC12CTL1 = SHS_1 + SHP + CONSEQ_2 ; // Use sampling timer, set mode

ADC12MCTL0 |= INCH_4 ; //Select input signal from A0 channel

delay_l(6) ;

ADC12CTL0 |= ENC ; // Enable conversions

CCTL0 = CCIE ; //Enable timerA Interrupt

TACCR0 = 4000; //Sample frequence about 1000Hz

TACCR1 = 2000 ;

TACCTL1 = OUTMOD_3 ; //PWM set/reset

TACTL = TASSEL_2 + MC_1 + TACLR ; //Use increase count mode

//TACTL = TASSEL_2 + MC_1 ;

_BIS_SR(LPM0_bits + GIE) ; // Enter LPM0 LOW-POWER0 MODE

}

/********************************************

//Intialized the SMCLK Clock

*********************************************/

void ClockInit()

{

BCSCTL1 &=~ XT2OFF ;

do

{

IFG1 &=~ OFIFG ;

for(uint i=0xff;i>0;i--) ;

}

while((IFG1 & OFIFG));

BCSCTL1 |= SELS | DIVS1 | DIVS0 ;

}

/*******************************************

USART初始化,选择波特率为9600,8位,无校验位

*******************************************/

void UartInit()

{

P3SEL |= 0x30 ; // P3.4,5 = USART0 TXD/RXD

ME1 |= URXE0 + UTXE0 ; // Enable USART0 T/RXD

UCTL0 |= CHAR ; // 8-bit character

UTCTL0 |= SSEL0 ; // UCLK = ACLK

//**Common used baud rates********************/

// UCLK---------Clock----------32k---------ACLK

// UxBR1=0x0,UxBR0=0x1B,UxMCTL=0x03---1200bit/s

UBR10 = 0x00 ; //SET BAUD // UxBR1=0x0,UxBR0=0x0D,UxMCTL=0x6B---2400bit/s

UBR00 = 0x06 ; // UxBR1=0x0,UxBR0=0x06,UxMCTL=0x6F---4800bit/s

UMCTL0 = 0x6f ;//Modulation // UxBR1=0x0,UxBR0=x03,UxMCTL=0x4A---9600bit/s

//************BAUD=2400Bit/s******************/

UCTL0 &= ~SWRST ; // Initialize USART state machine

IE1 |= URXIE0 ; //Open Transmit interrupt

}

/************************************************

定时器A中断服务程序把AD采集的数据放到

results[Num_of_Results]

************************************************/

#pragma vector=TIMERA0_VECTOR //TIMERA0_VECTOR INTERRUPT SERVICE

__interrupt void TIMERAISR (void) //ROUTINE

{

_BIC_SR(LPM0_bits) ;

temp = ADC12MEM0 ; //SAVE THE CONVERSATIN RESULT

ADDataTodecimal(value,temp); //Conversation HEX into DECIMAL

for(j = 0;j <= 3;j++)

{

value[j] += 0x30 ; //Conversation the DECIMAL into

}

SendDataToPC(value); //Transmit a serial of characters

//for(uint k=0x7f;k>0;k--);

} //per time

#pragma vector = UART0RX_VECTOR

__interrupt void receive_ISR(void)

{

_BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR)

if ( RXBUF0 == 0x31 )

{

UCTL0 |= SWRST;

ME1 &= ~UTXE0;

UCTL0 &= ~SWRST;

}

if ( RXBUF0 == 0x32 )

{

UCTL0 |= SWRST;

ME1 |= URXE0 + UTXE0 ; // Enable USART0 T/RXD

UCTL0 &= ~SWRST;

}

}

/***********************************

功能:发送数据给PC机

参数:*P指向被发送的数据的缓冲区

还回值:无

发送3位数据-----参考下面发送4位程序

***********************************/

void SendDataToPC(uchar *value)

{

while(*value != '/0') //JUDGE A CHARACTER IS END SIGN OR NOT

{

while(!(IFG1 & UTXIFG0)) ;//TRANSMIT COMPLETELY OR NOT

TXBUF0 = *value ;

value++ ;

}

while(!(IFG1 & UTXIFG0)) ;

TXBUF0 = '/n' ;

}

/*****************************/

void SendDataToPC1(uchar value)

{

while(!(IFG1 & UTXIFG0)) ;

TXBUF0 = value ;

while(!(IFG1 & UTXIFG0)) ;

TXBUF0 = '/n' ;

}

/********************************************

函数名称:ADDataTodecimal

功 能:将16进制ADC转换数据变换成十进制

表示形式

参 数:value--16进制数据

p--指向存放转换结果的指针

返回值 :无

********************************************/

void ADDataTodecimal(uchar *p,uint value)

{

p[0] = value / 1000 ; //THE THOUSAND BIT

p[1] = (value - p[0]*1000)/100 ; //THE HUNDRED BIT

p[2] = (value - p[0]*1000 - p[1]*100)/10 ; //THE DECIMAL BIT

p[3] = (value - p[0]*1000 - p[1]*100 - p[2]*10);// THE INDIVIDUAL BIT

}

/*******************************

功能:延时

**************************

void delay_l(int q)

{

int a,b;

for(a=0; a<q; a++ )

for(b=0;b<30000;b++);

}

上面的程序是MSP430F149的采用定时器定时触发A/D转换,并把转换好的数据发送到PC机,

Code:

// FormComDlg.cpp : implementation file

//

#include "stdafx.h"

#include "FormCom.h"

#include "FormComDlg.h"

#include "time.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CAboutDlg dialog used for App About

//int data[4096];

//#define Num 1000

class CAboutDlg : public CDialog

{

public:

CAboutDlg();

// Dialog Data

//{{AFX_DATA(CAboutDlg)

enum { IDD = IDD_ABOUTBOX };

//}}AFX_DATA

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CAboutDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

//}}AFX_VIRTUAL

// Implementation

protected:

//{{AFX_MSG(CAboutDlg)

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

//{{AFX_DATA_INIT(CAboutDlg)

//}}AFX_DATA_INIT

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CAboutDlg)

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

//{{AFX_MSG_MAP(CAboutDlg)

// No message handlers

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CFormComDlg dialog

CFormComDlg::CFormComDlg(CWnd* pParent /*=NULL*/)

: CDialog(CFormComDlg::IDD, pParent)

{

//{{AFX_DATA_INIT(CFormComDlg)

m_strReceiveData = _T("");

m_selcom = _T("");

m_selbaud = _T("");

//}}AFX_DATA_INIT

// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CFormComDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CFormComDlg)

DDX_Control(pDX, IDC_COMBO3, m_sendControlInfo);

DDX_Control(pDX, IDC_COMBO2, m_selbuadd);

DDX_Control(pDX, IDC_COMBO1, m_selcomm);

DDX_Control(pDX, IDC_EDIT2, m_ctrReceiveData);

DDX_Control(pDX, IDC_MSCOMM1, m_ctrComm);

DDX_Text(pDX, IDC_EDIT2, m_strReceiveData);

DDX_CBString(pDX, IDC_COMBO1, m_selcom);

DDX_CBString(pDX, IDC_COMBO2, m_selbaud);

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CFormComDlg, CDialog)

//{{AFX_MSG_MAP(CFormComDlg)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_BUTTON1_CLEARRECE, OnClearReceiveData)

ON_WM_TIMER()

ON_BN_CLICKED(IDC_SendData, OnSendData)

ON_BN_CLICKED(IDC_BUTTON1, On_CloseSerial)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CFormComDlg message handlers

BOOL CFormComDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog. The framework does this automatically

// when the application's main window is not a dialog

SetIcon(m_hIcon, TRUE); // Set big icon

SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

for(int i=0;i<ECGNum;i++)ECGdata[i]=0;

ecgnum=0;

// if (m_selcomm.GetCurSel()<0)

// i = 2;

// else

// i = m_selcomm.GetCurSel()+1;

m_ctrComm.SetCommPort(2);//选择端口COM2

// if (m_selbuadd.GetCurSel()<0)

// i = 2;

// else

/// i = m_selbuadd.GetCurSel();

//int n=m_selbuadd.GetLBTextLen(i);

// CString str;

// m_selbuadd.GetLBText(i,str);

// str += ",n,8,1";

m_ctrComm.SetInputMode(1);//输入方式为二进制

m_ctrComm.SetInBufferSize(4096);//设置输入缓冲区大小

m_ctrComm.SetOutBufferSize(512);//设置输出缓冲区大小

m_ctrComm.SetSettings("4800,n,8,1");//设置串口4800,N,8,1

if(!m_ctrComm.GetPortOpen())//检测串口是否打开

m_ctrComm.SetPortOpen(true);//打开串口

m_ctrComm.SetRThreshold(1);//参数1表示当串口接收缓冲区中有多于1或者等于1个

//字符将引发一个接收数据的OnCom事件

m_ctrComm.SetInputLen(0);//设置当前接收数据的长度为0

m_ctrComm.GetInput();//先预留缓冲区以清除残留数据

return TRUE; // return TRUE unless you set the focus to a control

}

void CFormComDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

if ((nID & 0xFFF0) == IDM_ABOUTBOX)

{

CAboutDlg dlgAbout;

dlgAbout.DoModal();

}

else

{

CDialog::OnSysCommand(nID, lParam);

}

}

// If you add a minimize button to your dialog, you will need the code below

// to draw the icon. For MFC applications using the document/view model,

// this is automatically done for you by the framework.

void CFormComDlg::OnPaint()

{

if (IsIconic())

{

CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle

int cxIcon = GetSystemMetrics(SM_CXICON);

int cyIcon = GetSystemMetrics(SM_CYICON);

CRect rect;

GetClientRect(&rect);

int x = (rect.Width() - cxIcon + 1) / 2;

int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon

dc.DrawIcon(x, y, m_hIcon);

}

else

{

CDialog::OnPaint();

}

}

// The system calls this to obtain the cursor to display while the user drags

// the minimized window.

HCURSOR CFormComDlg::OnQueryDragIcon()

{

return (HCURSOR) m_hIcon;

}

BEGIN_EVENTSINK_MAP(CFormComDlg, CDialog)

//{{AFX_EVENTSINK_MAP(CFormComDlg)

ON_EVENT(CFormComDlg, IDC_MSCOMM1, 1 /* OnComm */, OnComm, VTS_NONE)

//}}AFX_EVENTSINK_MAP

END_EVENTSINK_MAP()

/************************************************************************/

void CFormComDlg::OnComm()

{

//SetTimer(1,100,NULL);

LONG len=0,k=0;//定义从串口发送过来是数据长度

BYTE rxdata[1200];//定义一个存放从串口发送数据的BYTE类型的数组

CString strtemp=_T("0");//定义CString类型的变量实现BYTE类型转换为CString类型

// TODO: Add your control notification handler code here

COleVariant variant_inp;

COleSafeArray safearray_inp;//定义一个COleSafeArray的类型的变量实现串口数据类型与

if(m_ctrComm.GetCommEvent()==2)//判断串口接收缓冲区有没接收到数据

{

variant_inp.Attach(m_ctrComm.GetInput());//把串口缓冲区的数据读到variant_inp结构体中

safearray_inp=variant_inp;

len=safearray_inp.GetOneDimSize();

BOOL flag;

for(k=0;k<len;k++)

safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE数组

for(k=0;k<len;k++)//把BYTE的数组转换为CString

{

BYTE bt=*(char*)(rxdata+k);

strtemp.Format("%c",bt);

m_strReceiveData+=strtemp;//m_strReceiveData用来存储串口接收的所有数据

flag =true;

while(flag)//判断从串口接收的数据是否大于等于5个字节,如果满足这个条件

{

if(m_strReceiveData.GetLength()<5)

flag = false;

else

{

strtemp=m_strReceiveData.Left(4);//取conv字符串中的最左边四个字符,因为我发送过来的数据是5个字节,

//其中最后一个字节是一个‘/n

data[ecgnum]=_ttoi(strtemp);//两种数据的转换

num=(ecgnum+1)%ECGNum;//数组长度加1

m_strReceiveData.Delete(1,5);//删除已经转换的字符串

OnTimer(1);

}

}

strtemp=_T("0");//重新给这个变量进行初始化

}

}

UpdateData(false);

}

void CFormComDlg::OnClearReceiveData()

{

// TODO: Add your control notification handler code here

m_strReceiveData.Empty();//CLEAR THE CONTENT OF m_strReceiveData

for (int i = 0;i<=num-1;i++);

data[i] = 0;

num = 0;

UpdateData(false);//UPDATE THE DRAWING AREA,In principle the aim of this item

}

void CFormComDlg::DrawECG(CDC* pDC)

{

int i=0;

CRect rec;

CWnd* pWnd=GetDlgItem(IDC_STATIC12);//DIRECT TO DRAWING CONTROL

pWnd->GetClientRect(&rec);//DIRECT TO THE CLIENT PICTURE AREA

pDC->Rectangle(&rec);//DIRECTED THE PICTURE AREA

CPen* pPenRed = new CPen;//RED PEN

pPenRed->CreatePen(PS_SOLID,1,RGB(255,0, 0));

CPen* pOldPen=pDC->SelectObject(pPenRed);

int temp = 0;

for(i=0;i<num-1;i++)//pay attention to the consistent with coordinate between two point

{

pDC->MoveTo(rec.left+temp,data[i]/10-30);

pDC->LineTo(rec.left+1+temp,data[i+1]/10-30);

if(rec.left+1+temp>rec.Width()-10)

{

temp = 0;

}

else

temp = temp + 1;

}

pDC->SelectObject(pOldPen);

pWnd->ReleaseDC(pDC);

delete pPenRed;

}

/**********************************************************

/**********************************************************/

void CFormComDlg::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

CRect rect;

CWnd* pWnd = GetDlgItem(IDC_STATIC12);

pWnd->GetClientRect(&rect);

CDC* pDC = pWnd->GetDC();

pWnd->Invalidate();

pWnd->UpdateWindow();

CBitmap memBitmap;

CBitmap* pOldBmp = NULL;

memDC.CreateCompatibleDC(pDC);

memBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);

pOldBmp = memDC.SelectObject(&memBitmap);

memDC.BitBlt(rect.left,rect.top,rect.right,rect.bottom,pDC,0,0,SRCCOPY);

DrawECG(&memDC);

pDC->BitBlt(rect.left,rect.top,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);

memDC.SelectObject(pOldBmp);

memDC.DeleteDC();

memBitmap.DeleteObject();

pWnd->ReleaseDC(pDC);

CDialog::OnTimer(nIDEvent);

}

void CFormComDlg::OnSendData()

{

// TODO: Add your control notification handler code here

CString s;

int i;

if (m_sendControlInfo.GetCurSel()<0)

i=m_sendControlInfo.SetCurSel(1);

else

i = m_sendControlInfo.GetCurSel();

m_sendControlInfo.GetLBText(i,s);

m_ctrComm.SetOutput(COleVariant(s));

}

void CFormComDlg::On_CloseSerial()

{

// TODO: Add your control notification handler code here

if (m_ctrComm.GetPortOpen())

{

m_ctrComm.SetPortOpen(false);

}

else

{

m_ctrComm.SetPortOpen(true);

}

}

上面是MFC中的一部分程序

PC机可以正常的接收来自MSP430F149发送过来的数据,问题是,当我在关闭上位机的串口,然后重新打开串口接收时,就会出现乱码,有时是重新打开又可以正常接收;不过大多数还是显示乱码;

另外 PC机在正常接收时,当我点击COM选择组合框时,组合框的内容不停的闪烁,点击buadrate组合框时,也会不停的闪烁;不知道是什么问题?

本打算在上位机上发送 1 和 2来通知 MSP430F149关闭和打开串口结果是 发送1让MSP430F149停止发送可以实现,

1: PC机发送1给MSP430 通知MSP430关闭串口;

2:PC机发送2 给MSP430 通知MSP430打开串口,进行通信;

当发送2时,让MSP430F149重新打开串口,进行通信时就不能实现,请问各路高手 这到底是什么问题?

PC机程序如下

Code:

void CFormComDlg::OnSendData()

{

// TODO: Add your control notification handler code here

CString s;

int i;

i = m_sendControlInfo.GetCurSel();

m_sendControlInfo.GetLBText(i,s);

m_ctrComm.SetOutput(COleVariant(s));

}

MSP430F149的对应的程序如下

Code:

#pragma vector = UART0RX_VECTOR

__interrupt void receive_ISR(void)

{

_BIC_SR_IRQ(LPM3_bits);

if ( RXBUF0 == 0x31 )

{

UCTL0 |= SWRST;

ME1 &= ~UTXE0; //关闭串口发送功能

UCTL0 &= ~SWRST;

}

if ( RXBUF0 == 0x32 )

{

UCTL0 |= SWRST;

ME1 |= URXE0 + UTXE0 ; // Enable USART0 T/RXD

UCTL0 &= ~SWRST;

}

}

发现采用上面的办法 不能实现串口的关和闭,又采用用MS COMM控件来实现串口的关和闭 ,在正常情况下MSP430发送数据给PC机,PC机可以正常接收,当按下CloseSerial来关闭串口时,然后过会儿重新按下CloseSerial按钮 进行重新接收MSP430发送过来的数据时,就会出现乱码,请问高手用什么办法可以解决这个问题?PC机的程序如下

Code:

void CFormComDlg::On_CloseSerial()

{

// TODO: Add your control notification handler code here

if (m_ctrComm.GetPortOpen())

{

m_ctrComm.SetPortOpen(false);

}

else

{

m_ctrComm.SetPortOpen(true);

}

}

我的联系QQ 258130629

小弟 在此先谢谢各位高手啦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: