Share MSP430F149 and PC serial communication programming example
[Copy link]
/******************************************************************************
#include "msp430x14x.h" // Standard Equations
typedef unsigned char uchar ;
typedef unsigned int uint ;
/***********************************************
functional module
*******************************************/
void delay_l(int q);
void ClockInit() ; //Clock initialization
void UartInit() ; //Serial communication initialization function
void SendDataToPC(uchar *value); //Send data function
void SendDataToPC1(uchar value);
void ADDataTodecimal(uchar *p,uint value); //Hexadecimal to decimal conversion function
uchar value[5]; //Used to store a hexadecimal converted to decimal
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 frequency 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
}
/************************************************
Initialized the SMCLK Clock
*********************************************/
void ClockInit()
{
BCSCTL1
&
=~
}
/*******************************************
Initialize USART, select 9600 baud rate, 8 bits, no parity
**********************************************/
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
}
/****************************************************
Timer A interrupt service routine puts the data collected by AD into
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;
}
}
/***********************************
Function: Send data to PC
Parameter: *P points to the buffer of the data to be sent
Return value: None
Send 3-bit data-----refer to the following program to send 4 bits
***********************************/
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' ;
}
/****************************************
Function name: ADDataTodecimal
function Function: Convert hexadecimal ADC conversion data into decimal
representation
Parameter: value--hexadecimal data
p--pointer to store the conversion result
Return value: None
**********************************************/
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
}
/*******************************
Function: Delay
********************************
void delay_l(int q)
{
int a,b;
for(a=0; a<q; a++ )
for(b=0;b<30000;b++);
}
The above program is the MSP430F149 which uses the timer to trigger the A/D conversion and sends the converted data to the PC.
Code:
//FormComDlg.cpp:implementationfile
//
#include"stdafx.h"
#include"FormCom.h"
#include"FormComDlg.h"
#include"time.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
//intdata[4096];
//#defineNum1000
classCAboutDlg:publicCDialog
{
public:
CAboutDlg();
//DialogData
//{{AFX_DATA(CAboutDlg)
enum{IDD=IDD_ABOUTBOX};
//}}AFX_DATA
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
//}}AFX_VIRTUAL
//Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg():CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
voidCAboutDlg::DoDataExchange(CDataExchange*pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//Nomessagehandlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CFormComDlgdialog
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
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCFormComDlg::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()
/////////////////////////////////////////////////////////////////////////////
//CFormComDlgmessagehandlers
BOOLCFormComDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//TODO:Addextrainitializationhere
for(inti=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();
//intn=m_selbuadd.GetLBTextLen(i);
//CStringstr;
//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())//Check if the serial port is open
m_ctrComm.SetPortOpen(true);//Open the serial port
m_ctrComm.SetRThreshold(1);//Parameter 1 means that when there are more than 1 or equal to 1
//character in the serial port receive buffer, an OnCom event for receiving data will be triggered
m_ctrComm.SetInputLen(0);//Set the length of the current received data to 0
m_ctrComm.GetInput();//Reserve a buffer to clear the residual data
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.GetSafeH dc(), 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, CDia log)
//{{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;//Define the length of data sent from the serial port as
BYTE rxdata[1200];//Define an array of BYTE type to store the data sent from the serial port
CString strtemp=_T("0");//Define a variable of CString type to implement the conversion of BYTE type to CString type
// TODO: Add your control notification handler code here
COleVariant variant_inp;
COleSafeArray safearray_inp;//Define a variable of COleSafeArray type to implement serial port data type and
if(m_ctrComm.GetCommEvent()==2)//Judge whether the serial port receive buffer has received data
{
variant_inp.Attach(m_ctrComm.GetInput());//Read the data of the serial port buffer into the variant_inp structure
safearray_inp=variant_inp;
len=safearray_inp.GetOneDimSize();
BOOL flag;
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//Convert to BYTE array
for(k=0;k<len;k++)//Convert BYTE array to CString
{
BYTE bt=*(char*)(rxdata+k);
strtemp.Format("%c",bt);
m_strReceiveData+=strtemp;//m_strReceiveData is used to store all data received by the serial port
flag =true;
while(flag)//Judge whether the data received from the serial port is greater than or equal to 5 bytes. If this condition is met,
{
if(m_strReceiveData.GetLength()<5)
flag = false;
else
{
strtemp=m_strReceiveData.Left(4);//Take the leftmost four characters in the conv string, because the data I sent is 5 bytes,
//The last byte is a '/n
data[ecgnum]=_ttoi(strtemp);//Conversion of two types of data
num=(ecgnum+1)%ECGNum;//Array length plus 1
m_strReceiveData.Delete(1,5);//Delete the converted string
OnTimer(1);
}
}
strtemp=_T("0");//Reinitialize this variable
}
}
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->Select Object(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);
deletepPenRed;
}
/**********************************************************
/**********************************************************/
voidCFormComDlg::OnTimer(UINTnIDEvent)
{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
CRectrect;
CWnd*pWnd=GetDlgItem(IDC_STATIC12);
pWnd->GetClientRect(&rect);
CDC*pDC=pWnd->GetDC();
pWnd->Invalidate();
pWnd->UpdateWindow();
CBitmapmemBitmap;
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);
}
voidCFormComDlg::OnSendData()
{
//TODO:Addyourcontrolnotificationhandlercodehere
CStrings;
inti;
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));
}
voidCFormComDlg::On_CloseSerial()
{
//TODO:Addyourcontrolnotificationhandlercodehere
if(m_ctrComm.GetPortOpen())
{
m_ctrComm.SetPortOpen(false);
}
else
{
m_ctrComm.SetPortOpen(true);
}
}
上面是MFC中的一部分程序
PC机可以正常的接收来自MSP430F149发送过来的数据,问题是,当我在关闭上位机的串口,然后重新打开串口接收时,就会出现乱码,有时是重新打开又可以正常接收;不过大多数还是显示乱码;
In addition, when the PC is receiving normally, when I click on the COM selection combo box, the contents of the combo box keep flashing, and when I click on the buadrate combo box, it also keeps flashing. I don't know what the problem is?
I originally planned to send 1 and 2 on the host computer to notify MSP430F149 to close and open the serial port. As a result, sending 1 to stop MSP430F149 can be achieved.
1: PC sends 1 to MSP430 to notify MSP430 to close the serial port;
2: PC sends 2 to MSP430 to inform MSP430 to open the serial port for communication;
When 2 is sent, the MSP430F149 reopens the serial port, but communication cannot be achieved. Can any experts please tell me what the problem is?
The PC program is as follows
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));
}
The corresponding program for MSP430F149 is as follows
Code:
#pragma vector = UART0RX_VECTOR
__interrupt void receive_ISR(void)
{
_BIC_SR_IRQ(LPM3_bits);
if ( RXBUF0 == 0x31 )
{
UCTL0 |= SWRST;
ME1 &= ~UTXE0; //Disable serial port sending function
UCTL0 &= ~SWRST;
}
if ( RXBUF0 == 0x32 )
{
UCTL0 |= SWRST;
ME1 |= URXE0 + UTXE0 ; // Enable USART0 T/RXD
UCTL0 &= ~SWRST;
}
}
It is found that the above method cannot realize the opening and closing of the serial port, so the MS COMM control is used to close and close the serial port. Under normal circumstances, MSP430 sends data to PC, and PC can receive it normally. However, when CloseSerial is pressed to close the serial port, and then the CloseSerial button is pressed again to receive the data sent by MSP430, garbled characters will appear. Can any experts please tell me how to solve this problem? The PC program is as follows
Code:
voidCFormComDlg::On_CloseSerial()
{
//TODO:Addyourcontrolnotificationhandlercodehere
if(m_ctrComm.GetPortOpen())
{
m_ctrComm.SetPortOpen(false);
}
else
{
m_ctrComm.SetPortOpen(true);
}
}
|