CC2530 Basic Experiment 3: Uart

It's five months since the last hair
Paste the code. UART is the most commonly used serial communication mode. Each single chip microcomputer must bring at least one UART for communication, and CC2530 is no exception. Of course, the CC2530 is a Usart, that is, a universal synchronous asynchronous serial receiver transmitter, which can use asynchronous UART mode or synchronous SPI mode.

Code and analysis

#include <ioCC2530.h>
#include "string.h"

/****************************
This example simply uses the Usart module of CC2530.
After power on, it will automatically send a text through Uart.
The number "1" is sent when KET1 is pressed.
Send the number "0" to CC2530 in the serial port assistant, and the on-board LED1 will change the state.
****************************/

#define LED1 P1_0 / / LED1 is defined as P10 port control
#define KEY1 P0_1 / / define key1 as P01 port control

#define uchar unsigned char 
#define uint unsigned int 

/*Local function*/
void initUART(void);
void initLED(void);
void sendmsg(char *);
void delay(int n);

char temp=0;

int main(void)
{
  /*Initialize LED*/
  initLED();
  /*Initialize Uart*/
  initUART();
  
  sendmsg("New crown, new crown, leave!\r\n\r\n");
  
  while(1)
  {
    /*Uart Send relevant code snippets*/
    if(KEY1 == 0)   //If a key is pressed
    {
      delay(40);    //Delay to eliminate chattering
      if(KEY1 == 0)
      {
        sendmsg("1\r\n");   //The number 1 is sent when the key 1 is detected to be pressed
      }
    }
    
    /*Uart Accept relevant code snippets*/
    if(0 != temp)   //If Uart receives data
    {
      if(temp == 0x30)    //If you receive the number 0
      {
        LED1 = !LED1;   //Change LED1 status
      }
      temp = 0;   //Clear temp
    }
  }
}
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void) 
{ 
    URX0IF = 0;   //Clear interrupt flag bit
    temp = U0DBUF;    //Store the 8-bit data of the receive buffer into temp
}

void initLED(void)
{
  P1DIR |= 0x03;    //P1_0/P1_1 is defined as output
  LED1 = 1;   //LED1 lamp is initialized to off
}

void initUART(void)
{
  P0SEL |= 0x0C;    //Port 0_ 4/0_ 5 set as peripheral function
  U0GCR |= 11;
  U0BAUD |= 216;    //Set the baud rate to 57600
  U0CSR |= 0XC0;    //Set USART to the Uart function and enable the USART receiver
 			
  URX0IF = 0;   //Clear receive interrupt flag bit
  EA = 1;   //Turn on the main interrupt switch to use the interrupt function of the system
  URX0IE = 1;   //Usart0 interrupt function enable
}

/*Delay Functions */
void delay(int n)
{
  int i,j;
  for(i=0;i<n;i++)
    for(j=0;j<1000;j++);
}

/*Uart Send function*/
void sendmsg(char *data)
{
  while(1)
  {
    if('\0' == *data)   //Once the end of the string is detected, it exits. A string always ends with '\ 0'
    {
      break;
    }
    
    U0DBUF = *data++;   //Otherwise, the current character is passed into the send buffer
    while(UTX0IF == 0);   //Wait for the transmission to complete. After the transmission, UTX0IF will be automatically set to 1 by the system
    UTX0IF = 0;   //Clear send completion status
  }
}

Another version

Of course, there is a version with more code, which I checked when I was experimenting. DMA and FSM are used. Record it 😑, I'm too lazy to play 😬.

#include <ioCC2530.h>
#include "string.h"

/****************************
This example uses Usart and DMA. The data received by Uart is directly put into the array through DMA without CPU intervention.
A text will be sent after power on.
A packet structure is defined, with a total of five bits. The frame header is 0x0F,0x0D, then the packet length is 0x34, and then the data bits,
0x30 Turn off the light, 0x31 turn on the light, 0x37 switch the light state, and the last is the check bit, the XOR and sum of the first four bytes.
After sending the five bit data in hexadecimal without line break, CC2530 will continue to judge or output verification error according to the result of checksum,
After passing the verification, the FSM will verify the first three bytes. After successful verification, the lamp state will be switched, otherwise an error message will be output.
****************************/

#define LED1 P1_0
#define LED2 P1_1
#define KEY1 P0_1

#define uchar unsigned char 
#define uint unsigned int 

#pragma bitfields=reversed / / convert to small end mode
typedef struct 
{
  uchar SRCADDRH;        // High 8 bits of source address
  uchar SRCADDRL;        // Lower 8 bits of source address
  uchar DESTADDRH;       // 8 bits higher than the destination address
  uchar DESTADDRL;       // Lower 8 bits of destination address
  uchar VLEN          :3;// Length field mode selection
  uchar LENH          :5;// Transmission length high byte
  uchar LENL          :8;// Transmission length low byte
  uchar WORDSIZE      :1;// Byte or word transfer
  uchar TMODE         :2;// Transmission mode selection
  uchar TRIG          :5;// Trigger event selection
  uchar SRCINC        :2;// Source address increment: - 1 / 0 / 1 / 2
  uchar DESTINC       :2;// Destination address increment: - 1 / 0 / 1 / 2
  uchar IRQMASK       :1;// Interrupt mask
  uchar M8            :1;// 7 or 8bit transmission length, applicable only in byte transmission mode 
  uchar PRIORITY      :2;// priority
}DMA_DESC;
#pragma bitfields = default / / switch back to big end mode

DMA_DESC uartdma;      //DMA configuration parameter structure variable

void initUART(void);
void initLED(void);
void sendmsg(char *);
void receivemsg(void);
void delay(int n);
uint FSM(uchar *buff);
void changeled(uchar data);
uint xor(uchar *data);
void init_DMA();



uint count = 0;
char temp=0;
uchar buff[6];		//	You need to add one more byte as the terminator, otherwise an error will occur
//The starting field is defined as 0x0F 0x0D, and the package length is 4 bytes. The command code is: 1 for on, 0 for off, 7 for switching lamp status, and FCS for the first four bytes of XOR and
#define  STATE1  0x00
#define  STATE2  0x02
#define  STATE3  0x04
#define  STATE4  0x06
#define  STATE5  0x08

int main(void)
{
  
  initLED();
  init_DMA();
  initUART();
  
  sendmsg("New crown, new crown, leave!\r\n\r\n");
  
  while(1)
  {
    DMAARM |= 0x01;   //Put DMA channel 0 into operation
    DMAIRQ |= 0x00;   //Clear DMA transfer completion flag
    delay(500);   
    if(buff[4] != 0)    //If there are already five bits of data in the buff
    {  
       buff[5]='\0';
	sendmsg("The received packets are as follows:");
	sendmsg(buff);
	sendmsg("\r\n");
	if(xor(buff) == 1)
	{
	  if(FSM(buff) == 1)
	  {
	    sendmsg("The received packet is valid\r\n");
	  }
	  else
	  {
	    sendmsg("Invalid received packet\r\n");
	  }
	}
	else
	{
	  sendmsg("FCS error");
	}
	memset(buff,0,6);
    }
  }
}
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void) 
{ 
    URX0IF = 0;
    temp = U0DBUF;
}

void initLED(void)
{
  P1DIR |= 0x03;
  LED1 = 1;
  LED2 = 1;
}

void initUART(void)//9600
{
  P0SEL |= 0x0C;
  U0GCR |= 11;
  U0BAUD |= 216;
  U0CSR |= 0XC0;
 			
  UTX0IF = 0;
  URX0IF = 0;
  EA = 1;
  URX0IE = 1;
}

void delay(int n)//11us
{
  int i,j;
  for(i=0;i<n;i++)
    for(j=0;j<1000;j++);
}
void sendmsg(char *data)
{
  while(1)
  {
    if(*data=='\0')
      break;
    U0DBUF = *data++;
    while(UTX0IF == 0);
    UTX0IF = 0;
  }
}
 
uint FSM(uchar *buff)
{
	uchar state = STATE1;
	uchar data;
	uint flag = 0;
	
	while(1)
	{
		data = *buff++;
		switch(state)
		{
			case STATE1:
				if(data == 0x0F)
				{
					state = STATE2;
				}
				else
				  flag = 1;
				break;
			case STATE2:
				if(data == 0x0D)
				{
					state = STATE3;
				}
				else
				  flag = 1;
				break;
			case STATE3:
				if(data == 0x34)
				{
					state = STATE4;
				}
				else
				  flag = 1;
				break;
			case STATE4:	
				changeled(data);
				state = STATE5;
				break;
			default:
				break;
		}
		if(state == STATE5)
		{
			return 1;
		}
		if(flag == 1)
		{
			break;
		}
	}
	
	return 0;
}
void changeled(uchar data)
{
	if(data == 0x30)
		LED1 = 1;
	if(data == 0x31)
		LED1 = 0;
	if(data == 0x37)
		LED1 = !LED1;
}

/*check*/
uint xor(uchar *data)
{
  uchar temp = 0;
  
  /*XOR sum*/
  for(int i=0;i<4;i++)
  {
    temp ^= *data++;
  }

  sendmsg("FCS: ");   //Print XOR and view
  sendmsg(&temp);
  sendmsg("\r\n");
//  sendmsg(&(*data));
  if(temp == *data)
    return 1;
  else
    return 0;
}

void init_DMA()
{
  /*Configure source address*/    
  uartdma.SRCADDRH=(uchar)((uint)&X_U0DBUF>>8);    
  uartdma.SRCADDRL=(uchar)((uint)&X_U0DBUF&0x00ff);

  /*Configure destination address*/      
  uartdma.DESTADDRH=(uchar)((uint)&buff >> 8);    
  uartdma.DESTADDRL=(uchar)((uint)&buff&0x00FF);  
  
  /*Select LEN as the transfer length*/
  uartdma.VLEN=0x00;         //Select LEN as the transfer length
  
  /*Set transmission length*/
  uartdma.LENH=0;  
  uartdma.LENL=5;
  
  uartdma.WORDSIZE=0x00;     //Select byte transfer
  
  uartdma.TMODE=0x00;        //Byte mode
  
  uartdma.TRIG=14;           //Serial port receiving interrupt trigger
  
  uartdma.SRCINC=0x00;       //Source address increment is 0
  
  uartdma.DESTINC=0x01;      //The destination address is incremented by 1
  
  uartdma.IRQMASK=0;         //Clear DMA interrupt
    
  uartdma.M8=0x00;           //Select 8-bit long bytes to transmit data
  
  uartdma.PRIORITY=0x02;     //Transmission priority is high
  
  /*Assign the first address of the configuration structure to the relevant SFR*/
  DMA0CFGH=(uchar)((uint)&uartdma >> 8);   
  DMA0CFGL=(uchar)((uint)&uartdma & 0x00ff);
  
  asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
}
  • Learn about Usart of CC2530.

  • In line 72, first set the port corresponding to Usart 0 as a peripheral port. Usart is a peripheral. Only when it is set as a peripheral port can Usart send and receive data through Uart;
  • Lines 73-74, set the baud rate of Uart, as long as the data in the figure below are written into the register one by one, which is very simple. However, it should be noted that the default system clock of CC2530 in my hand is 16M. The following figure is the corresponding value of 32M baud rate register. Remember to be careful here. If your MCU system clock is 32M, you can write the register directly into the table. If it is 16M, like mine, the value of the register corresponding to baud rate in the following figure is written in, The actual baud rate will be halved. For example, if 115200 baud rate is selected, the corresponding U0GCR is 11 and U0BAUD is 216. After this is written in, the actual baud rate is 57600 under the 16M system clock. If the setting error will lead to garbled code, be careful.
  • Line 75, set Usart to Uart mode and enable reception.
  • Lines 77-79, open the interrupt related registers, including the total interrupt and the accept interrupt of Uart0. Of course, lines 78-79 can also directly IEN0 |= 0x84;

    There's nothing else to say. The general effect is like this. When powered on and sent once, the key will send 1, and replying to 0 will make the LED take the reverse state.

Summary

Uart is really commonly used. I have been practicing for a long time. In fact, although the company also uses protocols such as CAN, SPI and IIC, Uart is still the most commonly used, convenient and simple one. It's important to know about Uart. For the DMA used in the above complex point, let's put it down for the second time. DMA is still very good.

Tags: Single-Chip Microcomputer

Posted on Fri, 05 Nov 2021 19:06:47 -0400 by moleculo