用戶6897911226
個人電腦控制單片機要建立上位機和下位機的通訊連接
電腦(計算機)我們定義為上位機,單片機定義為下位機;兩者之間可以通過串口或者USB進行連接通訊;比較老的電腦還有並口,現在基本上已經沒有了。
串口連接通訊
一般的單片機都有UART接口,可以和電腦的串口進行通訊。
因為電腦的串口使用的是RS232電平,電平信號是+/-12V;而單片機的UART使用的是TTL電平,電平信號是5V(或者3.3V)。兩者是沒辦法直接溝通的,需要用到232芯片來進行“翻譯”
經過轉換的信號就可以通訊了。電腦串口的Rx(接收)要接到單片機的Tx(發送),電腦串口的Tx(發送)要接到單片機的Rx(接收);一邊發,另一邊就是收。
電腦沒有串口怎麼辦?
現在新的電腦,特別是筆計本,很多都取消了串口,那怎麼辦呢?我們可以使用USB轉TTL的模塊來進行轉換
USB轉UART的模塊的Rx接到單片機的Tx;Tx接到單片機的Rx就要以了;
USB直接通訊
功能比較強大的單片機,還有USB接口,可以連接電腦的USB接口進行通訊
硬件連接通了,還需要通訊程序配合
電腦和單片機都需要運行適當的程序才可以互相收發數據。就好比水管接好了,也需要有水的配合才可以哦。
歡迎關注@電子產品設計方案,一起享受分享與學習的樂趣!關注我,成為朋友,一起交流一起學習
- 記得點贊和評論哦!非常感謝
電子產品設計方案
個人電腦可以通過單片機仿真軟件、USB接口、串口、網口、無線、藍牙等方式控制單片機。
首先要說的一點是:想要實現個人電腦控制單片機,首先要讓單片機“願意”被控制,這個“願意”是指單片機程序裡面有能夠接受外部控制指令的功能,這樣才能實現,否則單片機就不能被控制。
一、通過單片機仿真軟件控制單片機
關於這種方式,我在“如何在線實時監控調試單片機程序運行”這個問答裡已經有過說明了,大家感興趣的話,可以去看看。這裡就不多說了。
二、通過USB口或串口控制單片機
個人電腦要實現通過USB口或串口控制單片機,首先要確保單片機電路板上有USB或者串口接口,並且還需要單片機程序裡面有通過USB或者串口控制單片機的功能程序。
在這種條件下,個人電腦可以用過USB連線、串口連線、USB轉串口連線等方式與單片機建立起通信機制,並且此時個人電腦要發送單片機能夠“聽懂”的話才行,也就是個人電腦和單片機雙方要遵循一定的通信機制,例如雙方事先規定好個人電腦發送“1”表示要讓LED燈亮,那麼單片機接收到這個“1”後,才會點亮LED。
三、通過網絡接口控制單片機
這種方式需要單片機電路板上有一個網絡模塊,然後電腦要連到這個網絡模塊所在的網絡上,這樣才能夠實現個人電腦控制單片機,一般情況下單片與網絡模塊的的鏈接是通過串口連接的,這樣就比較簡單了。
但是現在的ARM等都帶有網絡接口,這樣就不需要網絡模塊了,不過相應的就需要較為複雜的程序編寫。
四、通過無線、藍牙方式控制單片機
這種方式需要單片機電路上連接有無線、藍牙模塊。而計算機也需要連接無線、藍牙模塊。
對於本身具有無線或藍牙功能的單片機,只需要編寫複雜的相應通信程序。而對於只需通過串口連接的已經做好協議的藍牙或無線通信模塊,只需要根據指令編寫串口通信程序就可以了。
老馬識途單片機
個人電腦控制單片機,主要通過以下步驟:
1)建立個人電腦和單片機的通信連接
普通的單片機通常有UART、SPI、IIC、USB等通信模塊。
和電腦通信最常用的是UART,可以有兩種方式和電腦建立連接(現在的筆記本電腦很少有支持RS232的DB9接口,所以需要使用USB轉TTL,或者USB轉485的數據線):
從網上購買USB轉TTL的串口線:
通過UART-TTL,將單片機的串口TX,RX引出,加限流保護電阻之後,將串口線的地和單片機的地接到一起,將單片機的串口TX接到串口線的RX,將單片機的串口RX接到串口線的TX。
還可以通過RS485總線與電腦連接;
仍然從網上購買USB轉RS485的數據線:
RX,TX,以及發送/接收使能控制腳如下圖連接至485芯片(如MAX485),將單片機的串口轉成485總線。
除了串口之外,還可以從網上購買支持UART接口的以太網模塊或者wifi模塊。
通過以太網模塊,或者wifi模塊內置的TCP/IP協議棧,採用TCP/IP通信與個人電腦建立連接。
單片機與模塊之間的控制(如初始化、建立TCP客戶端/服務端,發送/接收TCP/UDP報文等)可以通過標準的AT指令實現。
2)制定協議以及編寫軟件
如果是通過RS485連接,建議採用MODBUS通信協議。
個人自定義協議,我通常採用如下格式:
1字節幀頭,2字節數據長度,1字節命令字,n字節payload,1字節crc8校驗
包括單片機軟件和上位機軟件,
不管是串口/RS485通信,還是TCP/IP通信,都是單片機串口的通信程序。
包括髮送和接收程序,一般開闢發送/接收兩塊緩存,在串口中斷接收程序中,將串口接收到的數據放在環行隊列,在主程序中根據協議從環行隊列中取出數據進行解析,當解析到有效數據之後,再拋給應用層程序進行相關處理(如IO口控制,IO口讀取,FLASH讀寫等)。
當應用層需要發送數據時,請求串口發送,將數據填入發送緩存,之後串口程序串口發送中斷程序中將數據逐字節送入串口發送寄存器。
以下是我在產品中實際使用的串口程序。
#include "Uart.h"
#include "IO.h"
#include "crc.h"
#include "Timer.h"
#include "Strs.h"
#include "WiFi.h"
#define P_UA_TX_P GPIOA
#define P_UA_TX_V 9
#define P_UA_RX_P GPIOA
#define P_UA_RX_V 10
#define UART_WIFI ((USART_TypeDef *) USART1_BASE)
STRUARecType g_ua_stRecRegs;
STRUASendType g_ua_stSendRegs;
#define ENABLE_UART_TX() {\\
UART_WIFI->CR1 |= USART_CR1_TXEIE;\\
}
//禁止發送中斷,使能接收
#define DISABLE_UART_TX() {\\
UART_WIFI->CR1 &= ~USART_CR1_TXEIE;\\
g_ua_stSendRegs.m_uchSendTimer = 0;\\
}
#define ENABLE_UART_INT() {\\
NVIC_EnableIRQ(USART1_IRQn);\\
}
void fnUA_Init(void);
void fnUA_RealTime(void);
void fnUA_IOInit(void);
void fnUA_RegInit(void);
void fnUA_IOInit(void)
{
//使能外設時鐘
U16 bandrate;
SET_IO_AFMODE_PP(P_UA_TX_P, P_UA_TX_V);
SET_IO_IN_WITHOUTPULLUP(P_UA_RX_P, P_UA_RX_V);
//復位UART1外設模塊
RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;
RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;
//使能外設時鐘
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
//使能UART功能
UART_WIFI->CR1 = 0; //OVER8=0:16bit sample;M=0:8data bits;PCE=0:parity disable;
UART_WIFI->CR2 = 0; //ABREN=0:Auto baud rate detection is disabled;one stop bit;
UART_WIFI->CR3 = 0; //OVRDIS=0: Overrun enable;ONEBIT=0: Three sample bit method;EIE=0: Error interrupt enable
// 24M FCK 配置波特率為19200U; 24000000/19200=1250(0x04e2)
bandrate = ((U32)SYSCLK_SYS_FREQ / 2 / (U32)115200);
UART_WIFI->BRR = bandrate;//);
UART_WIFI->SR |= (USART_SR_PE |USART_SR_FE|USART_SR_NE |USART_SR_ORE|USART_SR_TC);
//接收/接收中斷使能
UART_WIFI->CR1 |= USART_CR1_RE | USART_CR1_RXNEIE;
//發送使能
UART_WIFI->CR1\t|= USART_CR1_TE ; //TCIE = 0;TXEIE = 0;IDLEIE = 0;
//使能UART外設模塊
UART_WIFI->CR1 |= USART_CR1_UE;
ENABLE_UART_INT();
}
void fnUA_RegInit(void)
{
memset(&g_ua_stRecRegs, 0, sizeof(g_ua_stRecRegs));
memset(&g_ua_stSendRegs, 0, sizeof(g_ua_stSendRegs));
}
void fnUA_Init(void)
{
fnUA_RegInit();
fnUA_IOInit();
}
void USART1_IRQHandler(void)
{
unsigned char temp =0;
static U8 crc = 0;
//Receive Int
if(UART_WIFI->CR1 & USART_CR1_RXNEIE)
{
while(UART_WIFI->SR & USART_SR_RXNE)
{
temp = UART_WIFI->DR;
g_ua_stRecRegs.m_uchRingBuff[g_ua_stRecRegs.m_uchInP & (UA_RX_RINGBUFF_SIZE - 1)] = temp;
g_ua_stRecRegs.m_uchInP++;
}
}
//Transmitter Int
if(UART_WIFI->CR1 & USART_CR1_TXEIE)
{
if(UART_WIFI->SR & USART_SR_TXE)
{//UART發送中斷
if(g_ua_stSendRegs.m_uchIsSending)
{
if(0 == g_ua_stSendRegs.m_uchIndex)
{
crc = 0;
}
if(g_ua_stSendRegs.m_uchIndex < g_ua_stSendRegs.m_uchCount)
{
temp = g_ua_stSendRegs.m_uchBuff[g_ua_stSendRegs.m_uchIndex];
if(g_ua_stSendRegs.m_uchIndex == (g_ua_stSendRegs.m_uchCount - 1))
{
temp = crc;
}
else
{
crc += temp;
}
UART_WIFI->DR = temp;
g_ua_stSendRegs.m_uchIndex ++;
}
else
{
DISABLE_UART_TX();
g_ua_stSendRegs.m_uchIsSending = FALSE;
}
}
}
}
}
#define UA_RX_CHARTIME 8
void fnUA_RecMsg(void)
{
U16 outp;
U8 temp;
static U8 crc = 0;
if(g_tm_stTimerFlag.Bits.bTimer16ms)
{
if(g_ua_stRecRegs.m_uchCharTime)
{
g_ua_stRecRegs.m_uchCharTime--;
if(0 == g_ua_stRecRegs.m_uchCharTime)
{
g_ua_stRecRegs.m_uchPointer = 0;
}
}
}
if(FALSE == g_ua_stRecRegs.m_uchReceived)
{
while(g_ua_stRecRegs.m_uchInP != g_ua_stRecRegs.m_uchOutP)
{
outp = g_ua_stRecRegs.m_uchOutP & (UA_RX_RINGBUFF_SIZE - 1);
g_ua_stRecRegs.m_uchOutP++;
temp = g_ua_stRecRegs.m_uchRingBuff[outp];
if(0 == g_ua_stRecRegs.m_uchPointer)
{
if(0x55 == temp)
{
crc = 0;
g_ua_stRecRegs.m_uchPointer = 1;
}
}
else if(1 == g_ua_stRecRegs.m_uchPointer)
{
if(0xFF == temp)
{
g_ua_stRecRegs.m_uchPointer = 2;
}
else if(0x55 != temp)
{
g_ua_stRecRegs.m_uchPointer = 0;
}
}
else if(g_ua_stRecRegs.m_uchPointer <= 3)
{
g_ua_stRecRegs.m_uchBuff[g_ua_stRecRegs.m_uchPointer - 2] = temp;
g_ua_stRecRegs.m_uchLen = 0;
g_ua_stRecRegs.m_uchPointer ++;
}
else if(g_ua_stRecRegs.m_uchPointer <= 5)
{
g_ua_stRecRegs.m_uchLen = g_ua_stRecRegs.m_uchLen << 8;
g_ua_stRecRegs.m_uchLen |= (U16)temp;
g_ua_stRecRegs.m_uchBuff[g_ua_stRecRegs.m_uchPointer - 2] = temp;
g_ua_stRecRegs.m_uchPointer ++;
if(g_ua_stRecRegs.m_uchLen >= (UA_RX_BUFF_SIZE - 5)) //msgid, length;
{
g_ua_stRecRegs.m_uchPointer = 0;
}
}
else
{
g_ua_stRecRegs.m_uchBuff[g_ua_stRecRegs.m_uchPointer - 2] = temp;
g_ua_stRecRegs.m_uchPointer++;
if(g_ua_stRecRegs.m_uchPointer >= (g_ua_stRecRegs.m_uchLen + 7))
{
g_ua_stRecRegs.m_uchPointer = 0;
if(crc == temp)
{
g_ua_stRecRegs.m_uchRecvTimer = 6;
g_ua_stRecRegs.m_uchLen += 5;
fnWF_ResetDeadTime();
g_ua_stRecRegs.m_uchReceived = TRUE;
}
break;
}
}
crc += temp;
}
}
}
void fnUA_Monitor(void)
{
if(g_tm_stTimerFlag.Bits.bTimer16ms)
{
if(g_ua_stSendRegs.m_uchSendTimer)
{
g_ua_stSendRegs.m_uchSendTimer --;
if(0 == g_ua_stSendRegs.m_uchSendTimer)
{
fnUA_Init();
}
}
}
}
void fnUA_RealTime(void)
{
U32 data;
fnUA_Monitor();
fnUA_RecMsg();
if(g_tm_stTimerFlag.Bits.bTimer100ms){
if(g_ua_stRecRegs.m_uchRecvTimer)
{
g_ua_stRecRegs.m_uchRecvTimer--;
if(0 == g_ua_stRecRegs.m_uchRecvTimer)
{
g_ua_stRecRegs.m_uchReceived = FALSE;
}
}
}
}
U8 fnUA_SendReq(U16 msgid, U16 len)
{
U8 res = FALSE;
g_ua_stSendRegs.m_uchBuff[0] = 0x55;
g_ua_stSendRegs.m_uchBuff[1] = 0xFF;
g_ua_stSendRegs.m_uchBuff[2] = (U8)(msgid >> 8);
g_ua_stSendRegs.m_uchBuff[3] = (U8)msgid;
g_ua_stSendRegs.m_uchBuff[4] = (U8)(len >> 8);
g_ua_stSendRegs.m_uchBuff[5] = (U8)len;
g_ua_stSendRegs.m_uchCount = len + 7;
g_ua_stSendRegs.m_uchSendTimer = (200);
g_ua_stSendRegs.m_uchIndex = 0;
g_ua_stSendRegs.m_uchIsSending = TRUE;
ENABLE_UART_TX();
res = TRUE;
return(res);
}
U8 fnUA_IsSend(void)
{
U8 res = TRUE;
if(FALSE == g_ua_stSendRegs.m_uchIsSending)
{
res = FALSE;
}
return res;
}
簡單的調試,可以用串口調試工具,採用MODBUS協議的工業控制可以用wincc等組態軟件。
對於上位機軟件,需要選擇集成開發環境和編程語言。
這裡選擇非常多,可以用C語言的VC, PASCAL語言的delphi,腳本語言python,甚至可以用圖形化編程語言labview.
我個人比較喜歡用delphi,接下來講一下delphi的編程實現。
先在delphi上設計人機界面,比如下圖的界面。
採用MSCOMM或者SPCOMM實現串口通信。
根據用戶的操作發送數據給單片機,接收單片機的數據顯示在界面上,有些基本需要通過數據庫控件,採用access或者mysql數據庫,將採集到的數據保存下來。
IT自動化交流
電腦控制單片機,那麼電腦和單片機之間必須通訊。兩個設備之間的通訊方式有很多種,常用的有RS232、RS485、RS422、USB、CAN、以太網、藍牙、WIFI等通訊方式。
要使用某一通訊方式,單片機和電腦必須具有相應的通訊接口,個人電腦一般有RS232、USB、以太網、藍牙等通訊方式。
假設使用RS232通訊,電腦自帶有RS232接口,無需擴展,那麼單片機硬件必須設計有RS232接口,使用RS232延長線連接即可,接下來就是編寫軟件了,包括底層驅動程序,以實現電腦控制單片機,比如使用C++、C#等編寫人機交互界面,定義通信協議,編寫底層驅動,即可實現通過自己編寫的人機交互界面控制單片機。如果只是簡單的控制也可以使用串口調試助手直接給單片機發送命令,以達到控制單片機的目的。
也可以使用其他通訊方式,比如RS485、RS422、USB、CAN、以太網、藍牙、WIFI等都可以使用,但是單片機必須擴展相應的通訊接口,如電腦沒有相應的通訊接口,可以購買相應的通訊轉換器即可,比如使用CAN通訊,只需購買一個USB轉CAN的轉換器即可,USB直接連接電腦,轉換器CAN接口與單片機CAN接口相連。
使用WIFI、藍牙通訊方式,可以實現手機直接控制單片機,編寫一個控制單片機的手機APP軟件,配置好WIFI或藍牙協議,手機APP發送一個命令,通過手機WIFI或藍牙將信息傳輸至單片機WIFI或藍牙接收端,從而實現了手機直接控制單片機。WIFI或藍牙模塊可以直接淘寶上購買現成的也不貴。
技術閒聊
通過串口通信
串口通信主要用於實現系統之間的連接和數據交換。底層連接也就是硬件連接要基於串行接口來實現,上層協議需要我們自己分析和制定,通過軟件編程實現。
硬件連接
通信協議
軟件程序編寫主要是設置波特率、串口工作方式、數據位數、是否有校驗位等參數,在發送端按位發送,接收端按位接收,通信協是保障通信雙方正確接收數據的保證。
比方說軟件(晶振11.0592MHZ)編寫中串口初始化:
SCON=0x50; //10位數據 1位起始位 8位數據位 1位停止位
TMOD|=0x20;
TH1=0xfd; // 波特率9600bps
TL1=0xfd;
TR1=1;
IE|=0x10;
那麼上位機串口終端就同一樣要保持一致,才能保證正常收發。
控制實現
上位機(電腦)發送指令,單片機接收後解析,然後根據解析到的指令執行相關控制任務。
易學單片機
這個問題有兩種理解,一種是用電腦開發單片機程序,另一種是和單片機進行通訊,通過上位機軟件對單片機進行控制。
第一種需要有一定的編程基礎,根據單片機型號使用對應的IDE進行開發,keil,iar都是常見的單片機軟件開發工具。主要來說一下第二種理解吧。
單片機和電腦可以通過有線,無線兩種方式進行通信,常用的有線通信總線有uart,usb和網絡(rj45)。
1uart是最常見的,屬於全雙工通信,收發可以同時進行。早先這種串口都使用DB9連接器,單片機板子上需要用max232之類的芯片做電壓轉換。不過現在電腦主板很少有這種db9接口了,大部分單片機通過usb轉ttl芯片,通過usb口和電腦進行通信。
2usb通信也是常用的一種方式。電腦做為主機,單片機作為從機使用。這類單片機常見的有cpress68013等等。
3通過網線進行通信。使用這種方式時,一般要接網絡協議芯片,進行物理層的數據解析。常用的協議芯片有w5500等。
因為現在電腦上都集成了wifi和藍牙模塊,所以也可以實現無線控制單片機。單片機端使用藍牙/WIFI轉串口模塊,或者直接使用集成了wifi/藍牙的芯片進行開發就可以了。常用的wifi芯片有esp8266等等,常用的藍牙芯片有cc2541等等。
其實還有很多細節沒有提到,希望高手們補充交流!
蟻哥愛科技
居然只有一個提到SPI的,看來都不精。
eexpss
你所說的控制是指那種方式呢?是控制每一步的運行方式?例如在線仿真,程序內設置斷點,查看運行時變量的數值變化。還可以和單片機進行通訊,如使用串口,CAN,以太網等通訊方式和單片機進行數據交互,讀取單片機採集的信息,也可以向單片機發送指令,控制單片機。這就需要看單片機的應用場景了。初學者還可以使用Proteus軟件進行模擬調試。這是一款集仿真、原理圖,PCB設計於一體的軟件。對於單片機初學者來說,該軟件非常實用,不需要你有硬件電路即可通過仿真學習單片機的編程。
果樂果菓
電腦安裝一個串口調試軟件,或者根據你需要控制單片機的動作自定義串口數據協議用VB寫一個基於串口通訊的上位機軟件。在單片機程序中接收串口數據,單片機根據接收到的串口數據按照你自定義的協議做出相應的動作。電腦和單片機使用一個USB轉TTL模塊連接,某寶有賣。
新城26
單片機就如同一臺沒有系統的小電腦,主電腦想跟這臺小電腦怎麼連,就在這臺小電腦上添加什麼外設:網卡(有線、WIFI)、USB(轉換芯片)、串口均可,再添加對應驅動(上行編碼下載解碼對應程序),空間夠大、資源夠多的跑個小系統也未嘗不可!