久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

怎么用C語言在Linux下實現CC2530上位機

177次閱讀
沒有評論

共計 7503 個字符,預計需要花費 19 分鐘才能閱讀完成。

丸趣 TV 小編給大家分享一下怎么用 C 語言在 Linux 下實現 CC2530 上位機,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、環境簡介

1. 軟硬件環境

下位機:CC2530 OS:vmware + ubuntu

在這里彭老師采用的是 CC2530, 讀者也可以采用其他的板子,我們只需要該板子有串口,可以和 PC 通信,同時板子上有可設置的 led 燈、繼電器以及可以采集數據的傳感器即可。

2. 硬件連接圖

硬件連接圖如下:

該款 CC2530 已經集成了 CH340 芯片,usb 線連接電腦,即可被識別。

3. pc 下識別串口

如果該串口被 PC 獲取,名字為 COMn【n 為某整數】。

windows 下串口

4. ubuntu 下識別串口

首先需要 vmware 抓取串口【串口在同一時刻要么被 windows 抓取要么被 vmware 抓取】,按下圖所示,點擊連接即可:

虛擬機抓取串口

但是往往 ubuntu 中沒有 ch440 的驅動,經過實際測試,ubuntu14 及之前的版本都沒有這個驅動,ubuntu16 以上的版本有這個驅動。

如果沒有 ch440 驅動可以用以下方法安裝對應的驅動:

1 make 2 sudo make load 3 ls /dev/ttyUSB0

 

ubuntu 安裝串口驅動

按照上述步驟,會生成設備文件 **/dev/ttyUSB0**。

ls /dev/ttyUSB0 -l crw-rw---- 1 root dialout 188, 0 Jan 15 05:45 /dev/ttyUSB0

c : 字符設備 rw-rw—-:文件操作權限

188, 0:主次設備號

3、4 節提到的 usb 轉串口驅動和 linux 下驅動源碼后臺【GH】回復 ch440 即可獲得

【注意】如果是其他開發板,自行安裝其他的串口驅動。

二、模塊設計

上位機和下位機的通信往往都是通過串口,linux 下往往生成字符設備 ttyUSB0【有的是 ttyS0】,操作串口設備就只需要操作該字符設備即可。

下面我們設計上下位機的軟件模塊。

1. 信令

設計上位機,首先需要設計上位機下發給下位機的指令格式,上位機按照該指令格式發送命令給下位機,下位需嚴格按照該指令格式進行解析指令。

含義如下:

device:要操作的設備

data:對應的設備及其額外的數據

CRC:校驗碼

# : 信令終止符

信令格式可以根據需要擴展或者精簡。

其中 device 定義如下【可以根據實際情況進行擴展】:

#define DEV_ID_LED_ON 0X1 #define DEV_ID_LED_OFF 0X2 #define DEV_ID_DELAY 0X3 #define DEV_ID_GAS 0X4

【注意】為便于理解,我們暫不考慮效率問題。

2. 上傳數據

下位機需要采集傳感器的數據并通過串口上傳,數據結構定義如下:

struct data{ unsigned char device; unsigned char crc; unsigned short data; };

device 設備

data 采集的數據

crc 校驗碼

3. 功能模塊

現在就可以開始設計軟件的各個功能模塊了。

下位機

下位機流程圖

下位主要任務就是循環接收上位機通過串口下發的數據,然后解析該指令內容,操作對應的硬件。

上位機

上位機

上位機主要任務是打印菜單,由用戶針對菜單做出選擇,然后按照指令格式封裝命令,并通過串口將該命令下發給下位機。

三、下位機功能函數

cc2530 的操作原理,本文不討論,如果是其他開發板,只需要修改串口操作函數。

1. LED 初始化

/**************************************************************************** *  名   稱: InitLed() *  功   能:  設置 LED 燈相應的 IO 口  *  入口參數:  無  *  出口參數:  無  ****************************************************************************/ void InitLed(void) { P1DIR |= 0x01; //P1.0 定義為輸出口  LED1 = 0; }

2. 初始化 UART

/**************************************************************** *  名   稱: InitUart() *  功   能:  串口初始化函數  *  入口參數:  無  *  出口參數:  無  *****************************************************************/ void InitUart(void) { PERCFG = 0x00; // 外設控制寄存器  USART 0 的 IO 位置:0 為 P0 口位置 1  P0SEL = 0x0c; //P0_2,P0_3 用作串口(外設功能) P2DIR  = ~0xC0; //P0 優先作為 UART0 U0CSR |= 0x80; // 設置為 UART 方式  U0GCR |= 11; U0BAUD |= 216; // 波特率設為 115200 UTX0IF = 0; //UART0 TX 中斷標志初始置位 0  U0CSR |= 0x40; // 允許接收  IEN0 |= 0x84; // 開總中斷允許接收中斷  }

3. 串口發送函數

/********************************************************************** *  名   稱: UartSendString() *  功   能:  串口發送函數  *  入口參數: Data: 發送緩沖區  len: 發送長度  *  出口參數:  無  ***********************************************************************/ void UartSendString(char *Data, int len) { uint i; for(i=0; i  i++) { U0DBUF = *Data++; while(UTX0IF == 0); UTX0IF = 0; } }

4. 串口中斷處理函數

/********************************************************************** *  名   稱: UART0_ISR(void)  串口中斷處理函數  *  描   述:  當串口 0 產生接收中斷,將收到的數據保存在 RxBuf 中  **********************************************************************/ #pragma vector = URX0_VECTOR __interrupt void UART0_ISR(void) { URX0IF = 0; //  清中斷標志  RxBuf = U0DBUF; }

5. 煙霧傳感器數據讀取

/**************************************************************** *  名   稱: myApp_ReadGasLevel() *  功   能:  煙霧傳感器數據讀取  *  入口參數:  無  *  出口參數:  無  *****************************************************************/ uint16 myApp_ReadGasLevel( void ) { uint16 reading = 0; /* Enable channel */ ADCCFG |= 0x80; /* writing to this register starts the extra conversion */ ADCCON3 = 0x87; /* Wait for the conversion to be done */ while (!(ADCCON1   0x80)); /* Disable channel after done conversion */ ADCCFG  = (0x80 ^ 0xFF); /* Read the result */ reading = ADCH; reading |= (int16) (ADCH   8); reading  = 8; return (reading); }

6. LED 燈控制函數

/**************************************************************** *  名   稱: led_opt() *  功   能: LED 燈控制函數  *  入口參數: RxData:接收到的指令  flage:led 的操作,點亮或者關閉  *  出口參數:  無  *****************************************************************/ void led_opt(char RxData[],unsigned char flage) { switch(RxData[1]) { case 1: LED1 = (flage==DEV_ID_LED_ON)?ON:OFF; break; /* TBD for led2 led3*/ default: break; } return; }

7. 主程序

/**************************************************************************** *  主程序入口函數  ****************************************************************************/ void main(void) { CLKCONCMD  = ~0x40; // 設置系統時鐘源為 32MHZ 晶振  while(CLKCONSTA   0x40); // 等待晶振穩定為 32M CLKCONCMD  = ~0x47; // 設置系統主時鐘頻率為 32MHZ InitLed(); // 設置 LED 燈相應的 IO 口  InitUart(); // 串口初始化函數  UartState = UART0_RX; // 串口 0 默認處于接收模式  memset(RxData, 0, SIZE); while(1) { // 接收狀態  if(UartState == UART0_RX) { // 讀取數據,遇到字符 # 或者緩沖區字符數量超過 4 就設置 UartState 為 CONTROL_DEV 狀態  if(RxBuf != 0) { // 以 # 為結束符, 一次最多接收 4 個字符  if((RxBuf !=  #) (count   4)) { RxData[count++] = RxBuf; } else { // 判斷數據合法性,防止溢出  if(count  = 4) { // 計數清 0  count = 0; // 清空接收緩沖區  memset(RxData, 0, SIZE); } else{ // 進入發送狀態  UartState = CONTROL_DEV; } } RxBuf = 0; } } // 控制控制外設狀態  if(UartState == CONTROL_DEV) { // 判斷接收的數據合法性  //RxData[]: | device | data |crc | # | //check_crc: crc = device ^ data //if(RxData[2] == (RxData[0]^RxData[1])) { switch(RxData[0]) { case DEV_ID_LED_ON : led_opt(RxData,DEV_ID_LED_ON); break; case DEV_ID_LED_OFF: led_opt(RxData,DEV_ID_LED_OFF); break; case DEV_ID_DELAY: break; case DEV_ID_GAS: send_gas(); break; default: break; } } UartState = UART0_RX; count = 0; // 清空接收緩沖區  memset(RxData, 0, SIZE); } } }

四、上位機功能函數

結構體

#define DEV_ID_LED_ON 0X1 #define DEV_ID_LED_OFF 0X2 #define DEV_ID_DELAY 0X3 #define DEV_ID_GAS 0X4 struct data{ unsigned char device; unsigned char crc; unsigned short data; };

函數

void uart_init(void ) { int nset1,nset2; serial_fd = open(  /dev/ttyUSB0 , O_RDWR); if(serial_fd == -1) { printf( open() error\n  exit(1); } nset1 = set_opt(serial_fd, 115200, 8,  N , 1); if(nset2 == -1) { printf( set_opt() error\n  exit(1); } } int Menu() { int option; system( clear  printf( \n\t\t************************************************\n  printf( \n\t\t** ALARM SYSTERM **\n  printf( \n\t\t** 1----LED **\n  printf( \n\t\t** 2----GAS **\n  printf( \n\t\t** 0----EXIT **\n  printf( \n\t\t************************************************\n  while(1) { printf( Please choose what you want:   scanf( %d , option); if(option 0||option 2) printf(\t\t choose error!\n  else break; } return option; } // RxData[]: | device | data |crc | # | void led() { int lednum = 0; int onoff; char cmd[4]; // 選擇 led 燈  while(1) { printf( input led number :[1 2]\n#  scanf(%d , lednum); //check if(lednum 1 || lednum  2) { printf( invalid led number\n  system( clear  continue; }else{ break; } } printf(operation: 1 on , 0 off\n  scanf( %d , onoff); if(onoff == 1) { cmd[0] = DEV_ID_LED_ON; }else if(onoff == 0) { cmd[0] = DEV_ID_LED_OFF; }else{ printf( invalid led number\n  return; } cmd[1] = lednum; //fulfill crc area cmd[2] = cmd[0]^cmd[1]; cmd[3] =  # // 表示結束符  tcflush(serial_fd, TCIOFLUSH); int i = 0; for(i=0;i i++) { printf( %d  ,cmd[i]); } printf(\n  write(serial_fd, cmd,sizeof(cmd)); sleep(1); } // RxData[]: | device | data |crc | # | void gas() { int len ; unsigned short GasLevel; struct data msg; char gas[4]={0}; char cmd[4]; cmd[0] = DEV_ID_GAS; cmd[3] =  # // 表示結束符  write(serial_fd, cmd,sizeof(cmd)); sleep(1); len = read(serial_fd, msg,sizeof(struct data)); // 轉換讀取的 gas 數據格式  GasLevel = msg.data; gas[0] = GasLevel / 100 +  0  gas[1] = GasLevel / 10%10 +  0  gas[2] = GasLevel % 10 +  0  printf(%s\n ,gas); getchar(); } void run() { int x; while(1) { x=Menu(); switch(x) { case 1: led(); break; case 2: gas(); break; case 0: printf( \n\t\t exit!\n\n  close(serial_fd); exit(0); default: fg=1; break; } if(fg) break; } } int main() { uart_init(); run(); return 0; }

五、運行結果

1. 上位機運行界面

主菜單

2. 點亮 led 燈

點亮 led1:

3. 滅燈

熄滅 led1

4. 讀取煙霧傳感器數據

獲取煙霧數據

煙霧的數據是 079,可以點根華子,你會發現每次讀取的值都是在變化。

以上是“怎么用 C 語言在 Linux 下實現 CC2530 上位機”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-25發表,共計7503字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 南丰县| 泰和县| 大竹县| 牟定县| 常熟市| 尉氏县| 岐山县| 融水| 庆城县| 弥勒县| 清远市| 舒城县| 甘德县| 万宁市| 德惠市| 临潭县| 修水县| 武功县| 通化县| 尼玛县| 道真| 景德镇市| 隆德县| 阜南县| 从化市| 龙陵县| 禄劝| 双鸭山市| 常宁市| 兖州市| 华安县| 鄂州市| 巴青县| 上栗县| 鱼台县| 台北县| 昌吉市| 屏山县| 蕉岭县| 科尔| 福泉市|