IPV6 電位器實驗
時間:2018-09-20 來源:未知
【實驗目的】
熟悉contiki 操作系統
熟悉Ipv6 的通信協議
通過本實驗掌握stm32w108的ADC使用方法
【實驗環境】
Ipv6蜂鳴器控制模塊
VMware 虛擬機
PC機 XP、Window7/8
【實驗內容】
6.UI Thread UI線程。管理和更新UI。
編寫電位器的ADC程序,實現定時(4秒)向server端發送ADC采集的數據。
【實驗原理】

圖 電位器原理圖
有原理圖可知,電位器的引腳與STM32W108的PA_5引腳相連,查找芯片手冊ADC章節,可知PC_5引腳對應的ADC5通道。慢慢的滑動電位器,使得PA_5引腳上的電壓時發生變化,電壓變化和AD值變化成正比。
【實驗步驟】
打開VMware虛擬軟件,打開Ubuntu鏡像,進入Vi下的contiki-2.7-stm目錄文件夾,執行ls命令。

進入繼電器源碼文件,路徑如下:
/home/user/songl/contiki-2.7-stm/contiki-2.7-stm/examples/mbxxx/rpl-udp-VR

接著你只需打開udp-VR-client.c和udp- VR -server.c兩個文件,修改他們之間的通信協議。
【編譯程序】
執行命令:
./build.sh
會生成udp- VR -server.bin和udp- VR -client.bin兩個bin文件。
連接設備如下(請參照本章節驅動安裝及程序燒寫下的“鏡像燒寫”),注意任何模塊都可以作為服務端的底板,只需燒寫server程序即可。這里運用繼電器模塊做服務端。
燒寫程序:
服務端(M3網關)燒寫 udp-VR-server.bin。
客戶端(電位器)燒寫 udp-VR-client.bin

上圖M3網關模塊連接到PC機上,打開串口調試。查看服務端接收到的數據。分析數據的內容是否正確。
【實驗結果】
利用串口調試工具做實驗,打開串口調試工具,波特率115200、串口號(你的電腦的端口號)、點擊打開。
注意:要先把模塊的開關打開,等到串口上有數據后,用手撥動電位器,這時觀察串口調試助手的數據信息。讀到的AD值在上升。說明電位器的分的電壓值也在上升。
接收到的數據如下:

可以通過串口發送21 49 07 FE 56 00 0B B0 00 00 23 7E控制繼電器的開。
21 49: 為字符‘!I’
07 FE :設備地址 注意:07 為低八位地址,FE為高八位地址
56 :設備類型 ‘V’ ,是電位器
00 0B B0: ADC的數據值:12位AD值0B為高四位,B0為低8位。
23:當前電量
7E:校驗和。
【實驗參考代碼】
PROCESS_THREAD(udp_client_process, ev, data)
{
uint8_t result = 0;
uint8_t i = 0;/p>
txbuf[0] = '!';
txbuf[1] = 'I';
txbuf[2] = addresses_L;
txbuf[3] = addresses_H;
txbuf[4] = 'V';
PROCESS_BEGIN();
PROCESS_PAUSE();
// GPIO_DBGCFG |= (1<<5);
set_global_address();
PRINTF("UDP client process started\r\n");
print_local_addresses();
/* new connection with remote host */
client_conn = udp_new(NULL, UIP_HTONS(UDP_SERVER_PORT), NULL);
if(client_conn == NULL) {
PRINTF("No UDP connection available, exiting the process!\r\n");
PROCESS_EXIT();
}
udp_bind(client_conn, UIP_HTONS(UDP_CLIENT_PORT));
PRINTF("Created a connection with the server ");
PRINT6ADDR(&client_conn->ripaddr);
PRINTF(" local/remote port %u/%u\r\n",UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));
etimer_set(&et_send,CLOCK_SECOND/2);
while(1) {
PROCESS_YIELD();
if(ev == tcpip_event) {
tcpip_handler();
#if 0
if(rxlen == 7)
{
if(rxbuf[0] == '#' && rxbuf[1] == 'C'&& rxbuf[2] == 'I' && rxbuf[3] == 'r' && rxbuf[4] ==addresses_H && rxbuf[5] == addresses_L)
{
if((rxbuf[6] - '0') == Relay_on)
{
halGpioSet(PORTx_PIN(PORTC,2),1);
PRINTF(" Open Relay\n");
flag = 1;
}
else if((rxbuf[6] - '0') == Relay_off)
{
halGpioSet(PORTx_PIN(PORTC,2),0);
PRINTF("Close Relay\n ");
flag = 0;
}
rxlen = 0;
}
}
#endif
}
#if 0
if(ev == serial_line_event_message) {
if(*((uint8_t *)data) == 0x90)
continue;
txbuf[count++] = *((uint8_t *)data);
if (count == 24) {
uip_udp_packet_sendto(client_conn, (char *)txbuf, 24,&server_ipaddr, UIP_HTONS(UDP_SERVER_PORT));
count = 0;
}
}
#endif
if(ev == PROCESS_EVENT_TIMER)
{
unsigned int temp = temperature_sensor.value(0);
txbuf[7] = temp;
txbuf[6] = temp >> 8;
for(i=0;i<(11-2);i++)
{
result ^= txbuf[i+1];
}
txbuf[10] = result;
uip_udp_packet_sendto(client_conn, (char *)txbuf, 11,&server_ipaddr, UIP_HTONS(UDP_SERVER_PORT));
result = 0;
etimer_reset(&et_send);
}
}
PROCESS_END();
}
Client 向服務器發送數據,主要用到etimer事件PROCESS_EVENT_TIMER,etimer_set(&et_send,CLOCK_SECOND*4)設置需要的時間;默認CLOCK_SECOND 1000 毫秒,也就是說每個4秒就會產生一個PROCESS_EVENT_TIMER事件。因此四秒發送一次設備狀態數據。

