Hilfe benötigt: Serielle Schnittstelle in MFC Anwendung



  • Das OnSerialMsg musst Du natürlich in die Klasse einfügen, welche die Msg;ap hat. Und dort wowohl in die h-Datei als auch in die cpp-Datei, wo Du dann machen kannst was Du willst...
    Da sind soch MFC Beispiele dabei... schau die Dir doch mal an...



  • Also ich hab mir das MFC Beispiel jetzt zum xten mal ansgesehen und blicke immernoch nicht durch! Ich habe versucht das so weit wie möglich zu übernehmen. Es lässt sich ohne Fehler kompilieren aber beim Ausführen kommt eine Exception-Meldung.

    Ich will doch nur ein Byte senden und dann eine Nachricht haben, wenn die 3 Antwortbytes da sind 😞

    EDIT:

    Ich habe jetzt hier mal den Code:

    // MFC_Test_1View.cpp : Implementierung der Klasse CMFC_Test_1View
    //
    
    #include "stdafx.h"
    #include "MFC_Test_1.h"
    #include "SerialMFC.h"
    
    #include "MFC_Test_1Doc.h"
    #include "MFC_Test_1View.h"
    
    #include "PortsDlg.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    // CMFC_Test_1View
    
    IMPLEMENT_DYNCREATE(CMFC_Test_1View, CFormView)
    
    BEGIN_MESSAGE_MAP(CMFC_Test_1View, CFormView)
    	ON_COMMAND(ID_EINSTELLUNGEN_PORTS, &CMFC_Test_1View::OnEinstellungenPorts)
    	ON_BN_CLICKED(IDC_BUTTON1, &CMFC_Test_1View::OnBnClickedButton1)
    	ON_BN_CLICKED(IDC_BUTTON2, &CMFC_Test_1View::OnBnClickedButton2)
    	ON_BN_CLICKED(IDC_BUTTON3, &CMFC_Test_1View::OnBnClickedButton3)
    	ON_BN_CLICKED(IDC_BUTTON4, &CMFC_Test_1View::OnBnClickedButton4)
    	ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, &CMFC_Test_1View::OnNMCustomdrawSlider1)
    	ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER1, &CMFC_Test_1View::OnNMReleasedcaptureSlider1)
    	ON_BN_CLICKED(IDC_BUTTON5, &CMFC_Test_1View::OnBnClickedButton5)
    	ON_WM_SERIAL(OnSerialMsg)
    END_MESSAGE_MAP()
    
    // CMFC_Test_1View-Erstellung/Zerstörung
    
    CSerialMFC myPort1;
    
    CMFC_Test_1View::CMFC_Test_1View()
    	: CFormView(CMFC_Test_1View::IDD)
    	, wert(0)
    {
    	// TODO: Hier Code zur Konstruktion einfügen
    
    	myPort1.Open(_T("COM1"),this);
    	myPort1.Setup(CSerial::EBaud115200,CSerial::EData8,CSerial::EParNone,CSerial::EStop1);
    	myPort1.SetupHandshaking(CSerial::EHandshakeOff);
    	myPort1.SetupReadTimeouts(CSerial::EReadTimeoutNonblocking);
    }
    
    CMFC_Test_1View::~CMFC_Test_1View()
    {
    	myPort1.Close();
    }
    
    void CMFC_Test_1View::DoDataExchange(CDataExchange* pDX)
    {
    	CFormView::DoDataExchange(pDX);
    	DDX_Text(pDX, IDC_EDIT1, wert);
    	DDV_MinMaxInt(pDX, wert, 0, 1024);
    	DDX_Control(pDX, IDC_SLIDER1, m_CSlider1);
    	DDX_Control(pDX, IDC_EDIT2, Edit_Fuss);
    }
    
    BOOL CMFC_Test_1View::PreCreateWindow(CREATESTRUCT& cs)
    {
    	// TODO: Ändern Sie hier die Fensterklasse oder die Darstellung, indem Sie
    	//  CREATESTRUCT cs modifizieren.
    
    	return CFormView::PreCreateWindow(cs);
    }
    
    void CMFC_Test_1View::OnInitialUpdate()
    {
    	CFormView::OnInitialUpdate();
    	GetParentFrame()->RecalcLayout();
    	ResizeParentToFit();
    	m_CSlider1.SetRange(0,1023,false);
    	m_CSlider1.SetPos(520);
    }
    
    // CMFC_Test_1View-Diagnose
    
    #ifdef _DEBUG
    void CMFC_Test_1View::AssertValid() const
    {
    	CFormView::AssertValid();
    }
    
    void CMFC_Test_1View::Dump(CDumpContext& dc) const
    {
    	CFormView::Dump(dc);
    }
    
    CMFC_Test_1Doc* CMFC_Test_1View::GetDocument() const // Nicht-Debugversion ist inline
    {
    	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFC_Test_1Doc)));
    	return (CMFC_Test_1Doc*)m_pDocument;
    }
    #endif //_DEBUG
    
    // CMFC_Test_1View-Meldungshandler
    
    void CMFC_Test_1View::OnEinstellungenPorts()
    {
    	// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
    	CPortsDlg myPortsDlg;
    	int nRetValue;
    	nRetValue = myPortsDlg.DoModal();
    }
    
    void CMFC_Test_1View::OnBnClickedButton1()	// Handgelenk
    {
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
    	CEdit *pEntry = static_cast<CEdit*>(GetDlgItem(IDC_EDIT1));
    	CString EntryText;
    	pEntry->GetWindowTextW(EntryText);
    	int i;
    	i = _wtoi(EntryText);
    	unsigned char achse, hbyte, lbyte;
    	achse = 0xB2;
    	lbyte = i;
    	hbyte = i>>8;
    	myPort1.Write(&achse,1);
    	myPort1.Write(&hbyte,1);
    	myPort1.Write(&lbyte,1);
    }
    
    void CMFC_Test_1View::OnBnClickedButton2()	// Ellbogen
    {
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
    	CEdit *pEntry = static_cast<CEdit*>(GetDlgItem(IDC_EDIT1));
    	CString EntryText;
    	pEntry->GetWindowTextW(EntryText);
    	int i;
    	i = _wtoi(EntryText);
    	unsigned char achse, hbyte, lbyte;
    	achse = 0xB0;
    	lbyte = i;
    	hbyte = i>>8;
    	myPort1.Write(&achse,1);
    	myPort1.Write(&hbyte,1);
    	myPort1.Write(&lbyte,1);
    }
    
    void CMFC_Test_1View::OnBnClickedButton3()	// Schulter
    {
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
    	CEdit *pEntry = static_cast<CEdit*>(GetDlgItem(IDC_EDIT1));
    	CString EntryText;
    	pEntry->GetWindowTextW(EntryText);
    	int i;
    	i = _wtoi(EntryText);
    	unsigned char achse, hbyte, lbyte;
    	achse = 0xB1;
    	lbyte = i;
    	hbyte = i>>8;
    	myPort1.Write(&achse,1);
    	myPort1.Write(&hbyte,1);
    	myPort1.Write(&lbyte,1);
    }
    
    void CMFC_Test_1View::OnBnClickedButton4()	// Fuss
    {
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
    	CEdit *pEntry = static_cast<CEdit*>(GetDlgItem(IDC_EDIT1));
    	CString EntryText;
    	pEntry->GetWindowTextW(EntryText);
    	int i;
    	i = _wtoi(EntryText);
    	unsigned char achse, hbyte, lbyte;
    	achse = 0xB3;
    	lbyte = i;
    	hbyte = i>>8;
    	myPort1.Write(&achse,1);
    	myPort1.Write(&hbyte,1);
    	myPort1.Write(&lbyte,1);
    	m_CSlider1.SetPos(i);
    }
    
    void CMFC_Test_1View::OnNMCustomdrawSlider1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.	
    
    	*pResult = 0;
    }
    
    void CMFC_Test_1View::OnNMReleasedcaptureSlider1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
    	int i;
    	i = m_CSlider1.GetPos();
    	unsigned char achse, hbyte, lbyte;
    	achse = 0xB3;
    	lbyte = i;
    	hbyte = i>>8;
    	myPort1.Write(&achse,1);
    	myPort1.Write(&hbyte,1);
    	myPort1.Write(&lbyte,1);
    	*pResult = 0;
    }
    
    LRESULT CMFC_Test_1View::OnSerialMsg (WPARAM wParam, LPARAM /*lParam*/)
    {
    	CSerial::EEvent eEvent = CSerial::EEvent(LOWORD(wParam));
    	CSerial::EError eError = CSerial::EError(HIWORD(wParam));
    
    	if (eEvent & CSerial::EEventRecv)
    	{
    		//// Create a clean buffer
    		//DWORD dwRead;
    		//char szData[101];
    		//const int nBuflen = sizeof(szData)-1;
    
    		//// Obtain the data from the serial port
    		//do
    		//{
    		//	m_serial.Read(szData,nBuflen,&dwRead);
    		//	szData[dwRead] = '\0';
    
    		//	// Scan the string for unwanted characters
    		//	for (DWORD dwChar=0; dwChar<dwRead; dwChar++)
    		//	{
    		//		if (!isprint(szData[dwChar]) && !isspace(szData[dwChar]))
    		//		{
    		//			szData[dwChar] = '.';
    		//		}
    		//	}
    		//} while (dwRead == nBuflen);
    	}
    
    	return 0;
    }
    void CMFC_Test_1View::OnBnClickedButton5()
    {
    	// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
    	unsigned char achse, data[3];
    	achse=0xA3;
    	myPort1.Write(&achse,1);
    	//myPort1.Read(data,3);
    	//CString wert_string;
    	//wert_string.AppendFormat(_T("%i"),MAKEWORD(data[2],data[1]));
    	//Edit_Fuss.SetWindowTextW(wert_string);
    }
    

    Ich bekomme aber keine Message!



  • Wie kann man den diese ON_WM_SERIAL Nachricht mithilfe eines Assistenten hinzufügen? Ich glaube, dass da noch irgendwas fehlt, ich weiss aber nicht was!

    Bitte helft mir!



  • Was hast Du denn für ein Projekt? MDI?
    Bist Du sicher, dass Daten ankommen?
    Änder doch auch noch
     ON_WM_SERIAL(OnSerialMsg)
    nach
     ON_WM_SERIAL(&CMFC_Test_1View::OnSerialMsg)
    


  • Nein ich habe eine SDI Anwendung.
    Wenn ich an den µC den das Byte 0xA3 schicke dann antwortet dieser mit z.B. 0xA3 0x01 0x23. Ich weiss auch dass das funktioniert, da das ganze auch ankommt, wenn ich z.B. das hier mache:

    void CMFC_Test_1View::OnBnClickedButton5()
    {
        // TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
        unsigned char achse, data[3];
        achse=0xA3;
        myPort1.Write(&achse,1);
        myPort1.Read(data,3);
        CString wert_string;
        wert_string.AppendFormat(_T("%i"),MAKEWORD(data[2],data[1]));
        Edit_Fuss.SetWindowTextW(wert_string);
    }
    

    Nur wird auch hierbei keine Message ausgelöst.

    NACHTRAG: Ich habe ON_WM_SERIAL(&CMFC_Test_1View::OnSerialMsg) geschrieben und es geht trotzdem nicht. Der Breakpoint bei der Funktion CMFC_Test_1View::OnSerialMsg(...) wird nicht erreicht.



  • Vermutlich liegt es daran, dass Du die Serielle Klasse nicht im *Konstruktor* initialisieren darfst sondern erst in *OnCreate*!
    In Konstruktor ist nämlich das Fenster-Handle noch nicht gültig... und "Open" braucht ein gültiges Fensterhandle! (siehe unten!)

    Siehe das MFC-Beispiel:

    int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    	// Call base class
    	if (CWnd::OnCreate(lpCreateStruct) == -1)
    		return -1;
    
    	// Open the serial port
    	if (m_serial.Open(dlgComSelect.m_strComPort,this) != ERROR_SUCCESS)
    	{
    		AfxMessageBox(_T("Unable to open COM-port"),MB_ICONSTOP|MB_OK);
    		GetParent()->PostMessage(WM_CLOSE);
    		return 0;
    	}
    
    	return 0;
    }
    
    virtual LONG Open (LPCTSTR lpszDevice, CWnd* pwndDest, UINT nComMsg = WM_NULL, LPARAM lParam = 0, DWORD dwInQueue = 0, DWORD dwOutQueue = 0)
    	{ 
    		return CSerialWnd::Open(lpszDevice,pwndDest->GetSafeHwnd(),nComMsg,lParam,dwInQueue,dwOutQueue); 
    	}
    


  • Ok hab ich gemacht. Jetzt geht gar nix mehr...

    myPort1.Open() liefert 0 (müsste also ok sein).

    Trotzdem kann ich nicht mal mehr senden. Schade! War aber ein guter Hinweis. 😕



  • ⚠ HALT STOPP!!!

    Manchmal hilft ein Reset des µC! Es geht alles! Auch die Messages kommen jetzt an! 😃 😃 😃

    Also Danke für den Tipp

    Im Konstruktor ist nämlich das Fenster-Handle noch nicht gültig...

    Das war der richtige Treffer!



  • :xmas1:
    Hat jetzt aber lange gedauert, bis ich das gesehen hab... 🤡



  • Hallo Leute!

    Jetzt habe ich nochmal ein kleines Problem...

    Folgende Ausgangssituation: SDI Anwendung mit FormView

    Ich habe in der Doc Klasse meine serielle Schnittstelle angelegt. Jetzt möchte ich ja auch die entsprechenden Messages verarbeiten (und zwar in der Doc Klasse). .Open() akzeptiert den this Zeiger nicht da der nicht CWnd* ist. Mhhh ok. Dachte ich mir, ich gebe das MainFrame an und rufe von da aus eine Funktion in meiner Doc Klasse auf... Pustekuchen! "Unzulässiger Aufruf einer nicht statischen Memberfunktion" 😕 Was auch immer das bedeuten mag!

    Wie kann ich das noch lösen?


Anmelden zum Antworten