STM32F103和CC2530之间的串口通信问题

2019-08-20 16:11发布

      小弟最近在写Zigbee网关程序,需要用到CC2530和STM32F103ZET6之间的串口通信。两者的串口配置都是一样的,CC2530之间可以进行通讯,STM32之间也可以进行通讯;STM32发CC2530收也可以正常通讯,但是CC2530发、STM32收就不能正常通讯,请问这是怎么回事?求原子哥和大神指点,谢谢!       1)STM32串口通信程序:       void uart1_init(u32 bound){        //GPIO端口设置        GPIO_InitTypeDef GPIO_InitStructure;        USART_InitTypeDef USART_InitStructure;        NVIC_InitTypeDef NVIC_InitStructure;        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟          //USART1_TX   GPIOA.9       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出       GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9          //USART1_RX          GPIOA.10初始化       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入       GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10             //Usart1 NVIC 配置        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  //USART1中断通道        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器          //USART 初始化设置        USART_InitStructure.USART_BaudRate = bound;//串口波特率        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位        USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式       USART_Init(USART1, &USART_InitStructure); //初始化串口1       USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断       USART_Cmd(USART1, ENABLE);                    //使能串口1 }       void USART1_IRQHandler(void)      {        u8 res;         if(USART_GetITStatus(USART1,USART_IT_RXNE))         {             res= USART_ReceiveData(USART1);              USART_SendData(USART1,res);                             while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);                 }     }     2)CC2530串口通信程序:[size=14.399999618530273px]     #include <ioCC2530.h>     #include <string.h>     #define uint unsigned int     #define uchar unsigned char    //定义控制LED灯的端口    #define LED1 P1_0    //定义LED1为P10口控制    #define LED2 P1_1    //定义LED1为P11口控制    //函数声明    void Delayms(uint xms);    //延时函数    void InitLed(void);        //初始化P1口    void InitUart();           //初始化串口    void Uart_Send_String(char *Data,int len);    char Rxdata[50];    uchar RXTXflag = 1;     char temp;     uchar  datanumber = 0;/****************************          延时函数*****************************/void Delayms(uint xms)   {  uint i,j;  for(i=xms;i>0;i--)    for(j=587;j>0;j--);}  /****************************//初始化程序*****************************/void InitLed(void){  P1DIR |= 0x03; //P10、P11定义为输出  LED1 = 0;     //关LED1  LED2 = 0;     //关LD2}/****************************************************************    串口初始化函数     ***********************************************************/void InitUart(){    CLKCONCMD &= ~0x40;      // 设置系统时钟源为 32MHZ晶振    while(CLKCONSTA & 0x40);    // 等待晶振稳定     CLKCONCMD &= ~0x47;      // 设置系统主时钟频率为 32MHZ    SLEEPCMD|=0x04;        //关闭不用的RC振荡器        PERCFG = 0x00;           //使用串口1的备用位置1 P0口     P0SEL  = 0x3c;           //P0_2,P0_3,P0_4,P0_5用作串口,第二功能     P2DIR &= ~0XC0;         //P0优先作为UART0 ,优先级        U0CSR |= 0x80;           //UART 方式     U0GCR |= 8;              //U0GCR与U0BAUD配合         U0BAUD |= 59;           //波特率设为9600    UTX0IF = 1;              //UART0 TX 中断标志初始置位1  (收发时候)    U0CSR |= 0X40;           //允许接收     IEN0 |= 0x84;             //开总中断,接收中断    }/**************************************************************** 串口发送字符串函数    ****************************************************************/ void Uart_Send_String(char *Data,int len) {     int j;     for(j=0;j<len;j++)     {         U0DBUF = *Data++;         while(UTX0IF == 0);      //发送完成标志位        UTX0IF = 0;    //UART0 TX中断标志清0    } }/***************************//主函数***************************/void main(void){    InitLed();                //调用初始化函数     InitUart();    while(1)    {            if(RXTXflag == 1) //接收状态         {             LED1=1;    //接收状态指示             if( temp != 0)             {                 //'#'被定义为结束字符,最多能接收50个字符                if((temp!='#')&&(datanumber<50))                 {                    Rxdata[datanumber++] = temp;                 }                else                 {                     RXTXflag = 3; //进入发送状态                     LED1=0;     //关指示灯                }                 temp  = 0;            }        }        if(RXTXflag == 3)     //发送状态         {             LED2= 1;                                       U0CSR &= ~0x40;   //禁止接收             Uart_Send_String(Rxdata,datanumber); //发送已记录的字符串。            U0CSR |= 0x40;    //允许接收             RXTXflag = 1;     //恢复到接收状态             datanumber = 0;    //指针归0             LED2 = 0;         //关发送指示         }      }}/**************************************************************** 串口接收一个字符: 一旦有数据从串口传至CC2530, 则进入中断,将接收到的数据赋值给全局变量temp. ****************************************************************/ #pragma vector = URX0_VECTOR __interrupt void UART0_ISR(void) {     URX0IF = 0;    //清中断标志     temp = U0DBUF;                           }[size=14.399999618530273px]
  
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
23条回答
BMN李
1楼-- · 2019-08-20 17:21
这个排版,无敌了。。。
fgh_asd
2楼-- · 2019-08-20 17:43
[mw_shl_code=c,true]
刚才发的太乱,再重新发一遍代码!
1)STM32串口通信程序:
void uart1_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
         
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
  
        //USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX          GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
   
  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  //USART1中断通道
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置
        USART_InitStructure.USART_BaudRate = bound;//串口波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1
}
//USART1串口中断程序
void USART1_IRQHandler(void)
{
        u8 res;
         if(USART_GetITStatus(USART1,USART_IT_RXNE))
  {
     res= USART_ReceiveData(USART1);
     USART_SendData(USART1,res);
                        
                while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);       
  }
}


2)CC2530串口通信程序:
#include <ioCC2530.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯的端口
#define LED1 P1_0    //定义LED1为P10口控制
#define LED2 P1_1    //定义LED1为P11口控制
//函数声明
void Delayms(uint xms);    //延时函数
void InitLed(void);        //初始化P1口
void InitUart();           //初始化串口
void Uart_Send_String(char *Data,int len);
char Rxdata[50];
uchar RXTXflag = 1;
char temp;
uchar  datanumber = 0;
/****************************
          延时函数
*****************************/
void Delayms(uint xms)   
{
  uint i,j;
  for(i=xms;i>0;i--)
    for(j=587;j>0;j--);
}  
/****************************
//初始化程序
*****************************/
void InitLed(void)
{
  P1DIR |= 0x03; //P10、P11定义为输出
  LED1 = 0;     //关LED1
  LED2 = 0;     //关LD2
}

/****************************************************************
   串口初始化函数     
***********************************************************/
void InitUart()
{
    CLKCONCMD &= ~0x40;      // 设置系统时钟源为 32MHZ晶振
    while(CLKCONSTA & 0x40);    // 等待晶振稳定
    CLKCONCMD &= ~0x47;      // 设置系统主时钟频率为 32MHZ
    SLEEPCMD|=0x04;        //关闭不用的RC振荡器
   
    PERCFG = 0x00;           //使用串口1的备用位置1 P0口
    P0SEL  = 0x3c;           //P0_2,P0_3,P0_4,P0_5用作串口,第二功能
    P2DIR &= ~0XC0;         //P0优先作为UART0 ,优先级
   
    U0CSR |= 0x80;           //UART 方式
    U0GCR |= 8;              //U0GCR与U0BAUD配合     
    U0BAUD |= 59;           //波特率设为9600
    UTX0IF = 1;              //UART0 TX 中断标志初始置位1  (收发时候)
    U0CSR |= 0X40;           //允许接收
    IEN0 |= 0x84;             //开总中断,接收中断   
}
/****************************************************************
串口发送字符串函数   
****************************************************************/
void Uart_Send_String(char *Data,int len)
{
    int j;
    for(j=0;j<len;j++)
    {
        U0DBUF = *Data++;
        while(UTX0IF == 0);      //发送完成标志位
        UTX0IF = 0;    //UART0 TX中断标志清0
    }
}


/***************************
//主函数
***************************/
void main(void)
{
    InitLed();                //调用初始化函数
    InitUart();
    while(1)
    {
      
      if(RXTXflag == 1) //接收状态
        {
            LED1=1;    //接收状态指示
            if( temp != 0)
            {
                //'#'被定义为结束字符,最多能接收50个字符
                if((temp!='#')&&(datanumber<50))
                {
                    Rxdata[datanumber++] = temp;
                }
                else
                {
                    RXTXflag = 3; //进入发送状态
                    LED1=0;     //关指示灯
                }
                temp  = 0;
            }
        }
        if(RXTXflag == 3)     //发送状态
        {
            LED2= 1;                           
            U0CSR &= ~0x40;   //禁止接收
            Uart_Send_String(Rxdata,datanumber); //发送已记录的字符串。
            U0CSR |= 0x40;    //允许接收
            RXTXflag = 1;     //恢复到接收状态
            datanumber = 0;    //指针归0
            LED2 = 0;         //关发送指示
        }  
    }
}
/****************************************************************
串口接收一个字符: 一旦有数据从串口传至CC2530, 则进入中断,
将接收到的数据赋值给全局变量temp.
****************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
    URX0IF = 0;    //清中断标志
    temp = U0DBUF;                           
}
[/mw_shl_code]
xuande
3楼-- · 2019-08-20 21:51

单向通信正常,说明配置没问题,最多就是IO口不对,比如配置不通,或者硬件连接有问题。

可以让发送方不间断地发数据,用示波器观察其Tx端,看波形是否正常。
如果正常,说明是接收方的问题;否则是发送方的问题。
这样把故障分区,然后仔细查找原因。


Switch
4楼-- · 2019-08-20 23:07
fgh_asd 发表于 2016-1-25 20:27
[mw_shl_code=c,true]
刚才发的太乱,再重新发一遍代码!
1)STM32串口通信程序:

可以试着把stm32的串口字长改为9位数据格式
USART_InitStructure.USART_WordLength = USART_WordLength_9b
fgh_asd
5楼-- · 2019-08-21 04:32
 精彩回答 2  元偷偷看……
fgh_asd
6楼-- · 2019-08-21 08:08
xuande 发表于 2016-1-25 20:36
单向通信正常,说明配置没问题,最多就是IO口不对,比如配置不通,或者硬件连接有问题。

可以让发送方 ...

STM32发数据给CC2530行,但反过来就不行。但我试过CC2530两者互发是可以的,我估计是CC2530发数据出来STM32的RX端根本接收不了,难道是串口电平兼容性的问题?

一周热门 更多>