0、 Preface

Netizens' questions are as follows :

 Fans ask questions
 The project framework
Between local processes
msg Message queue ,

Two pc Between
socket /unix
raw Socket :

BSD socket 
unix ->   bill joy  bsd Branch ,

Summarize the questions of this netizen , In fact, it is to implement a gateway program , The content is divided into several parts :

  1. Lower machine , Connect with PC through serial port ;
  2. The lower computer should be able to receive commands from the upper computer , And parse these commands ;
  3. The lower computer can configure corresponding peripherals according to these commands 、 Read the data of the corresponding sensor and upload it to the upper computer ;
  4. Main program serial port operation module : Send command through serial port or read data information uploaded by lower computer ;
  5. Main program network communication module : Receive command from remote server , And upload the data collected by the lower computer to the server .

On the whole , This is a small project , The content is quite difficult , Now we will divide it into several independent articles to explain .

This article only discusses how to write a simple upper computer for the lower computer .

One 、 Introduction to the environment

1. Hardware and software environment

Lower machine :CC2530
OS:vmware + ubuntu

Here Mr. Peng uses CC2530, Readers can also use other boards , We just need the board to have a serial port , You can talk to PC signal communication , At the same time, there are settable led The lamp 、 Relay and sensor can collect data .

2. Hardware connection diagram

The hardware connection diagram is as follows :
 Physical connection diagram
This paragraph CC2530 It's integrated CH340 chip ,usb Cable to computer , Can be identified .

3. pc Next, identify the serial port

If the serial port is PC obtain , The name is COMn【n Is an integer 】.

windows Lower serial port

4. ubuntu Next, identify the serial port

The first thing you need to vmware Grab the serial port 【 The serial port is either windows Grab or be vmware Grab 】, As shown in the figure below , Click connect :

 The virtual machine grabs the serial port

But often ubuntu There is no ch340 The driver , After actual testing ,ubuntu14 And previous versions don't have this driver ,ubuntu16 The above version has this driver .

without ch340 Drivers can be installed in the following ways :

1 make 
2 sudo make load3 ls /dev/ttyUSB0

ubuntu Install serial driver

Follow these steps , Will generate device files **/dev/ttyUSB0**.

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

c : Character device
rw-rw---- : File operation authority
188, 0 : Primary and secondary equipment number

3、4 As mentioned in section usb To serial port driver and linux Under the driver source background 【GH】 reply ch340 You can get

【 Be careful 】
If it's another development board , Install other serial drivers by yourself .

Two 、 Module design

The communication between upper computer and lower computer is usually through serial port ,linux Character generation devices are often used ttyUSB0【 There are plenty of them ttyS0】, To operate a serial port device, you only need to operate the character device .

Next, we design the software module of the upper and lower computer .

1. Signaling

Design the upper computer , First of all, we need to design the instruction format from the upper computer to the lower computer , The upper computer sends commands to the lower computer according to the command format , The lower part should analyze the instruction strictly according to the instruction format .

 Signaling format
The meaning is as follows :

  • device: The equipment to be operated
  • data : The corresponding device and its additional data
  • CRC : Check code
  • # : Signaling Terminator

The signaling format can be expanded or simplified as needed .

among device The definition is as follows 【 It can be expanded according to the actual situation 】:

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

【 Be careful 】
For the sake of understanding , Let's not think about efficiency for the moment .

2. Upload data

The lower computer needs to collect the sensor data and upload it through the serial port , The data structure is defined as follows :

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

  • device equipment
  • data Collected data
  • crc Check code

3. Function module

Now we can start to design the various functional modules of the software .

Lower machine

 Lower computer flow chart

The main task of the lower part is to receive the data sent by the upper computer through the serial port , Then parse the instruction content , Operate the corresponding hardware .

Upper computer

 Upper computer

The main task of the upper computer is to print the menu , It's up to the user to make choices for the menu , Then encapsulate the command in the instruction format , And send the command to the lower computer through the serial port .

3、 ... and 、 Function of lower computer

cc2530 How it works , Not covered in this article , If it's another development board , Just modify the serial port operation function .

1. LED initialization

*  name      call : InitLed()
*  work      can :  Set up LED The lights correspond to IO mouth
*  Entrance parameters :  nothing
*  Export parameters :  nothing
****************************************************************************/void InitLed(void){P1DIR |= 0x01;               //P1.0 Defined as the output port LED1 = 0;   }

2. initialization UART

*  name      call : InitUart()
*  work      can :  Serial initialization function
*  Entrance parameters :  nothing
*  Export parameters :  nothing
*****************************************************************/void InitUart(void){ 
    PERCFG = 0x00;           // Peripheral control register  USART 0 Of IO Location :0 by P0 Mouth position 1 P0SEL = 0x0c;            //P0_2,P0_3 Used as a serial port ( Peripheral functions )P2DIR &= ~0xC0;          //P0 Give priority to UART0
    U0CSR |= 0x80;           // Set to UART The way U0GCR |= 11;   
    U0BAUD |= 216;           // The baud rate is set to 115200UTX0IF = 0;              //UART0 TX The interrupt flag is initially set 0U0CSR |= 0x40;           // Allow to receive  IEN0 |= 0x84;            // Open total interrupt allows to receive interrupt   }

3. Serial port sending function

*  name      call : UartSendString()
*  work      can :  Serial port sending function
*  Entrance parameters : Data: Send buffer    len: Sending length
*  Export parameters :  nothing
***********************************************************************/void UartSendString(char *Data, int len){uint i;for(i=0; i<len; i++){U0DBUF = *Data++;while(UTX0IF == 0);UTX0IF = 0;}}

4. Serial interrupt processing function

*  name      call : UART0_ISR(void)  Serial interrupt processing function  
*  Sketch      Statement :  When serial port 0 A receive interrupt is generated , Save the received data in RxBuf in
**********************************************************************/#pragma vector = URX0_VECTOR __interrupt void UART0_ISR(void) { 
    URX0IF = 0;       //  Clear the interrupt flag  RxBuf = U0DBUF;                           }

5. Smoke sensor data reading

*  name      call : myApp_ReadGasLevel()
*  work      can :  Smoke sensor data reading
*  Entrance parameters :  nothing
*  Export parameters :  nothing
*****************************************************************/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 Light control function

*  name      call : led_opt()
*  work      can : LED Light control function
*  Entrance parameters :  RxData: Received instructions   flage:led The operation of , Turn it on or off
*  Export parameters :  nothing
*****************************************************************/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. The main program

*  Main program entry function
****************************************************************************/void main(void){
CLKCONCMD &= ~0x40;           // Set the system clock source to 32MHZ Crystal oscillator while(CLKCONSTA & 0x40);      // Wait for the crystal oscillator to stabilize to 32M
CLKCONCMD &= ~0x47;           // Set the system master clock frequency to 32MHZ   InitLed();                    // Set up LED The lights correspond to IO mouth InitUart();                   // Serial initialization function    
UartState = UART0_RX;         // A serial port 0 It is in receive mode by default memset(RxData, 0, SIZE);  
while(1){ // Reception status  if(UartState == UART0_RX)             
{ // Reading data , Characters encountered '#' Or the number of buffer characters exceeds 4 Is set UartState by CONTROL_DEV state if(RxBuf != 0) 
// With '#' End of character , Receive at most at one time 4 Characters        if((RxBuf != '#')&&(count < 4))     
RxData[count++] = RxBuf; 
 // Judge the validity of data , Prevent overflow if(count >= 4)            
// Count clear 0
count = 0;             
// Clear receive buffer memset(RxData, 0, SIZE);}else{// Enter the sending State  
UartState = CONTROL_DEV;}}
RxBuf  = 0;}}// Control peripheral state  if(UartState == CONTROL_DEV)            {// Judge the validity of the received data //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;     
// Clear receive buffer memset(RxData, 0, SIZE);           

Four 、 Function of upper computer


#define DEV_ID_LED_ON    0X1#define DEV_ID_LED_OFF    0X2#define DEV_ID_DELAY 0X3#define DEV_ID_GAS  0X4struct 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"); 
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];// choice led The lamp 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] = '#';// It means the ending 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] = '#';// It means the ending write(serial_fd,&cmd,sizeof(cmd));sleep(1);
len = read(serial_fd,&msg,sizeof(struct data));// Convert read gas data format
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){
{case 1:led();break;case 2:gas();break; 
case 0:printf("\n\t\t     exit!\n\n");close(serial_fd);exit(0);default:
 }}int main() {uart_init();run();return 0;}

5、 ... and 、 Running results

1. The upper computer running interface

 The main menu

2. Lighten up led The lamp

Lighten up led1:
 Lighten up led1

3. Lights out

 Extinguish led1

4. Read smoke sensor data

 Get smoke data

The data for smog is 079, Sure Point huazi , You'll find that every time you read the value is changing .

So far, , A simple CC2530 The upper computer is finished , If you want to send the value of the data obtained from the serial port to the remote server , We will continue to discuss in the following articles .

Code background reply ,**【cc2530 Upper computer 】** You can get .