?? client.c
字號:
#include "client.h"
const u8 UDP_Data[] = "This is the lwIP example about UDP client.\r\n";
/*ADC為12位模數轉換器,只有ADCConvertedValue的低12位有效*/
__IO uint32_t ADCConvertedValue;
u16 ADCConvertedValueLocal1,ADCConvertedValueLocal2;
u16 Voltage[2]={0}; //保存ADC轉換的電壓值(4位整數值)
u8 Data[8]={0}; //保存轉換后的ASCII字符
u8 Data1[8]={0}; //發送的數據(ADC1轉換值)
u8 Data2[8]={0}; //發送的數據(ADC2轉換值)
u8 zifu[] = "V\r\n";
u8 divstr[] = "----------\r\n";
struct ip_addr destAddr; //遠程主機IP地址
/******************************************************************************
** Function name: mux_n
** Descriptions: 計算10的n次冪,n要大于等于0
** input parameters: n : 10的n次冪
** output parameters: sum: 返回運算后的結果
** Returned value: 無
******************************************************************************/
u32 mux_n (u8 n)
{
u8 i;
u32 sum = 10;
for (i = 1; i < n; i++)
sum = sum * 10;
if (n == 0) sum = 1;
return sum;
}
/******************************************************************************
** Function name: Data_ASICC
** Descriptions: 將一個最大值四位的整數轉換為字符串
** input parameters: charge_data: 要轉換的3位整數
** output parameters: 無
** Returned value: 無
******************************************************************************/
void Data_ASICC (u16 charge_data)
{
u8 i,index = 0;
u16 ulchar, temp;
for (i = 0; i < 4; i++)
{
ulchar = charge_data / (mux_n(3 - i)) % 10 + '0'; //取出最高位
Data[index++] = ulchar;
if (i == 0)
Data[index++]='.'; //小數點
ulchar = (ulchar - '0'); //下面四條語句是將最高位消除,為下次再取一個最高位做準備
temp = (mux_n(3 - i));
ulchar = ulchar * temp;
charge_data = charge_data - ulchar;
}
Data[index++] = 'V';
Data[index++] = '\r';
Data[index] = '\n';
}
/******************************************************************************
** Function name: HexToASCII
** Descriptions: 將二進制數轉換成ASCII字符
** input parameters: data: 要轉換的整數
** output parameters: 無
** Returned value: 無
******************************************************************************/
void HexToASCII(u16 data)
{
Data[0] = data/1000%10 + 0x30;
Data[1] = '.';
Data[2] = data/100%10 + 0x30;
Data[3] = data/10%10 + 0x30;
Data[4] = data%10 + 0x30;
Data[5] = 'V';
Data[6] = '\r';
Data[7] = '\n';
}
//復制字符數組的內容
void data_cpy(u8 *dest, u8 *src)
{
u8 i = 0;
for(i = 0;i < 8;i++)
{
dest[i] = src[i];
}
}
void Get_ADC_Data(void)
{
ADCConvertedValueLocal1 = (ADCConvertedValue&0x00000fff);
Voltage[0] = (ADCConvertedValueLocal1*3300/4096); //PC0電壓值 //將電壓值*1000,保存成整數
ADCConvertedValueLocal2 = ((ADCConvertedValue>>16)&0x00000fff);
Voltage[1] = (ADCConvertedValueLocal2*3300/4096); //PC1電壓值 //0x1000
Delay(200000); //原來的延時參數為8000000
}
//注意,ADC采樣后的VOLTAGE已經是一個四位數,可以直接轉換為ASIIC碼輸出
void Turn_ADC_Data(void)
{
HexToASCII(Voltage[0]);
// Data_ASICC(Voltage[0]); //PC0電壓值
data_cpy(Data1,Data);
HexToASCII(Voltage[1]);
// Data_ASICC(Voltage[1]); //PC1電壓值
data_cpy(Data2,Data);
Delay(500000);
}
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能DMA時鐘*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* 使能ADC1、ADC2和GPIOC端口*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_GPIOC, ENABLE);
/* 配置PC0作為ADC的模擬量輸入,作為ADC通道1的模擬通道10 */
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* DMA1通道1參數配置*/
DMA_DeInit(DMA1_Channel1);/*失能DMA1通道1*/
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; /*指定DMA的外設地址為ADC1的數據寄存器地址*/
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;/*指定DMA的內存基地址*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; /*外設作為數據傳輸來源*/
DMA_InitStructure.DMA_BufferSize = 2; /*2個數據單位,即32位*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /*外設地址寄存器不變*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; /*內存地址寄存器不變*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; /*數據寬度為字,16位*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; /*設定外設數據寬度*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; /*工作在循環緩存模式*/
DMA_InitStructure.DMA_Priority = DMA_Priority_High; /*DMAx通道擁有高優先級*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /*DMAx通道沒有設置為內存到內存傳輸*/
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/*使能DMA1通道1*/
DMA_Cmd(DMA1_Channel1, ENABLE);
/*ADC1配置*/
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; /*ADC工作在同步規則模式*/
ADC_InitStructure.ADC_ScanConvMode = ENABLE; /*掃描模式*/
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /*連續模式*/
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /*軟件啟動*/
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /*數據右對齊*/
ADC_InitStructure.ADC_NbrOfChannel = 1; /*一個ADC通道進行規則轉換*/
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Init(ADC2, &ADC_InitStructure);
/* 設置ADC1的采樣順序和轉換時間*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); //PC0
/*使能ADC1的DMA請求*/
ADC_DMACmd(ADC1, ENABLE);
/*使能ADC1*/
ADC_Cmd(ADC1, ENABLE);
/*使能ADC1重置校準寄存器*/
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
/*開始指定ADC1的校準狀態*/
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
/* ADC1軟轉換開始*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
/*ADC2的配置*/
ADC_RegularChannelConfig(ADC2, ADC_Channel_13, 1, ADC_SampleTime_71Cycles5); //PC3
ADC_DMACmd(ADC2, ENABLE);
ADC_Cmd(ADC2, ENABLE);
ADC_ResetCalibration(ADC2);
while(ADC_GetResetCalibrationStatus(ADC2));
ADC_StartCalibration(ADC2);
while(ADC_GetCalibrationStatus(ADC2));
/* ADC2軟轉換開始*/
ADC_SoftwareStartConvCmd(ADC2, ENABLE);
}
/**
* @brief Initialize the UDP client and then UDP server application.
* @param None
* @retval None
*/
void client_init(void)
{
struct udp_pcb *upcb;
struct pbuf *p;
// p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(UDP_Data), PBUF_RAM);
p->payload = (void *)UDP_Data;
/* Create a new UDP control block */
upcb = udp_new();
/* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
udp_bind(upcb,IP_ADDR_ANY,UDP_CLIENT_PORT); //STM32_UDP客戶端的端口:121
/* Connect the upcb */
udp_connect(upcb, IP_ADDR_BROADCAST, UDP_SERVER_PORT); //IP_ADDR_BROADCAST : 0xffffffffUL (上位機UDP服務器端口:120)
/* Send out an UDP datagram to inform the server that we have strated a client application */
udp_send(upcb, p);
udp_send(upcb, p);
udp_send(upcb, p); //連續發送三次
/* Reset the upcb */
udp_disconnect(upcb);
/* Bind the upcb to any IP address and the UDP_PORT port*/
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT); //原來是UDP_CLIENT_PORT (STM32_UDP服務器的端口:120)
/* Set a receive callback for the upcb */
udp_recv(upcb, udp_server_callback, NULL);
/* Free the p buffer */
pbuf_free(p);
}
/**
* @brief This function is called when an UDP datagrm has been received on the port UDP_PORT.
* @param arg : user supplied argument (udp_pcb.recv_arg)
* @param upcb: the udp_pcb which received data
* @param p : the packet buffer that was received
* @param addr: the remote IP address from which the packet was received
* @param port: the remote port from which the packet was received
* @retval None
*/
void udp_server_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
{
__IO uint8_t iptab[4];
uint8_t iptxt[20];
destAddr = *addr; //獲得遠程主機的IP地址(STM32的TCP客戶端和遠程主機連接時需要)
/* Read the Client's IP address */
iptab[0] = (uint8_t)((uint32_t)(addr->addr) >> 24);
iptab[1] = (uint8_t)((uint32_t)(addr->addr) >> 16);
iptab[2] = (uint8_t)((uint32_t)(addr->addr) >> 8);
iptab[3] = (uint8_t)((uint32_t)(addr->addr));
sprintf((char*)iptxt, "%d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]);
/* Display the client's IP address */
/* If there is more than one client connected, the IP address of the last one connected will be displayed */
printf("The client port : %d\n",port);
printf("The client IP address : %s\n",iptxt);
/* Connect to the remote client */
udp_connect(upcb, addr, port);
/* Tell the client that we have accepted it */
udp_send(upcb, p);
// udp_sendto(upcb,p,addr,port); //用此函數,UDP客戶端為什么收不到數據呢?!
GPIOD->ODR ^= GPIO_Pin_4; //LED3閃爍(表示STM32的UDP客戶端接收到數據)
/* free the UDP connection, so we can accept new clients */
udp_disconnect(upcb);
/* Free the p buffer */
pbuf_free(p);
}
void TCP_Client_Init(void)
{
struct tcp_pcb *pcb;
// struct ip_addr destAddr;
// IP4_ADDR(&destAddr,192,168,4,123); //1.指定遠程主機IP地址; 2.通過接收UDP客戶端數據包,獲取遠程主機IP地址
/* Create a new TCP control block */
pcb = tcp_new();
/* Assign to the new pcb a local IP address and a port number */
tcp_bind(pcb, IP_ADDR_ANY, TCP_PORT);
/* Connect to the server: send the SYN */
tcp_connect(pcb, &destAddr, TCP_PORT, tcp_client_connected);
}
/*與遠程服務器建立連接時調用*/
err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
tcp_write(tpcb,Data1,sizeof(Data1),0);
// tcp_write(tpcb,zifu,sizeof(zifu),0);
tcp_write(tpcb,Data2,sizeof(Data2),0);
// tcp_write(tpcb,zifu,sizeof(zifu),0);
tcp_write(tpcb,divstr,sizeof(divstr),0);
tcp_close(tpcb);
return ERR_OK;
}
//疑問:在STM32上建立TCP客戶端,向遠程主機(TCP服務器)發送連接請求。當連接正確時,
// 調用此回調函數發送數據,發送完畢關閉連接。
// 一次調用回調函數為什么無法發送多個字符串?即遇到字符串結束符號'\0',便終
// 止了后續tcp_write() 函數發送的內容。
//解決:sizeof(Data)求字符串的長度,包括了字符串結束符\0';
// strlen(Data)求字符串的長度,指字符串的實際長度。
//程序中用 tcp_write(tpcb,Data,strlen(Data),0); 便解決此問題。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -