千家信息网

怎么用C语言在Linux下实现CC2530上位机

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,小编给大家分享一下怎么用C语言在Linux下实现CC2530上位机,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、环境简
千家信息网最后更新 2026年10月31日怎么用C语言在Linux下实现CC2530上位机

小编给大家分享一下怎么用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

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<4;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 + '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上位机"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

串口 数据 函数 参数 设备 驱动 指令 入口 字符 格式 传感器 功能 烟雾 出口 控制 设计 模块 状态 缓冲区 缓冲 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 江苏根荣互联网科技 为想互联网科技 唐信互联网科技 互联网科技论坛 互联网科技英文翻译 科技大学互联网专业好不好 安控科技rtu产品工业互联网 互联网科技博主是什么意思 北京华百购互联网科技有限公司 茂名市互联网科技产业园 南山科技园互联网公司有哪些 福建科技产业互联网发展 昊天互联网科技有限公司 苏州铭阳互联网科技有限公司 乌苏新华互联网科技做什么的 东营紫格互联网科技 互联网科技手机排行榜 艺电能源互联网科技有限公司招聘 中国互联网公司的科技投入 玉溪新华互联网科技怎么选 科技信息互联网 为想互联网科技 西藏七维空间互联网科技有限公司 银川新华互联网科技职业技术培训学校图片 互联网金融科技展 皮皮虾互联网科技有限公司 21世纪互联网科技成就 半导体是互联网高科技吗 互联网科技收购价值 数字科技和互联网金融哪个好
0