和电脑通信最常用的是UART,可以有两种方式和电脑建立连接(现在的笔记本电脑很少有支持RS232的DB9接口,所以需要使用USB转TTL,或者USB转485的数据线):
通过UART-TTL,将单片机的串口TX,RX引出,加限流保护电阻之后,将串口线的地和单片机的地接到一起,将单片机的串口TX接到串口线的RX,将单片机的串口RX接到串口线的TX。
包括发送和接收程序,一般开辟发送/接收两块缓存,在串口中断接收程序中,将串口接收到的数据放在环行队列,在主程序中根据协议从环行队列中取出数据进行解析,当解析到有效数据之后,再抛给应用层程序进行相关处理(如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 |= 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;
}
这里选择非常多,可以用C语言的VC, PASCAL语言的delphi,脚本语言python,甚至可以用图形化编程语言labview.