STM32与C51串口通信

2019-08-14 19:09发布

最近做了一个STM32与C51串口通信, 不用电平转换,就是用USART通信。今天试验8051到8051,8051与PC,STM32 到PC都能通信,波特率9600。但是用STM32与8051串口通信就不可以了。把SM32的变量i的数值传到80C51上并用LCD1602显示,请大家看是什么问题!要实现的通信结构图如下:

1、C51代码部分:
//C51串口通信 -双机通信
#include "usart.h"    //发送数据
//input:k
//output:none
void Send(uchar k)
{
 SBUF=k;     //P3.1输出
 while(TI==0);
 TI=0; 
} //定时器T1初始化
//input:none
//output:none
void T1_Init(void)
{
 TMOD=0x20; // 选择T1工作于方式2,选择可自动加载初值的8位计数器
 SCON=0x50; //工作方式1为8位UART
 CON=0x00;   //电源控制寄存器
 TH1=0xFD;      //9600bit/s
 TL1=0xFD;
 TR1=1;
}



#include <REGX52.H> 
#include "delay.h"
#include "key.h"
#include "lcd1602.h"
#include "usart.h"
 
#define uchar unsigned char
#define unit unsigned int char R_data=0;
char code table_code[]={'0','1','2','3','4','5','6','7','8','9',
      'A','B','C','D','E','F','H','I','J','K',
      'L','N','M','O','P','Q','R','S','T','U',
      'V','W','X','Y','Z','+','-','*','/','='};//转换成液晶显示的字符
        //主程序                                        
int main()
{
 char i;     //按键值缓存区
    
 LCD_Init();  //液晶初始化
 T1_Init();   // 串口初始化
 while(1)
  {  i=key_scanf();   //取得按键值
 LCD_Write_String(0,0,"T_DATA:") ;  //显示发关数据
 LCD_Write_String(0,1,"R_DATA:") ;  //显示接收数据      switch(i)
  {
  
  case 1: LCD_Write_Char(8,0,table_code[1]) ; Send(1);break;   //发送数据
  case 2: LCD_Write_Char(8,0,table_code[2]) ; Send(2);break;
  case 3: LCD_Write_Char(8,0,table_code[3]) ;Send(3);break;
  case 4: LCD_Write_Char(8,0,table_code[4]) ; Send(4);break;
  default: ; break;
  }   if(RI==1)      //接收数据标志
   {
   R_data=SBUF;
   RI=0;
   }            LCD_Write_Char(8,1,table_code[R_data]) ; //显示接收数据    }


2、STM32代码部分:用原子哥的视频《入门(KEIL安装+JTAG调试+串口下载+新建工程)》

#include<stm32f10x_lib.h>
#include"sys.h"
#include"delay.h"
#include"usart.h" int main(void)
{
 u8 i=0;
 Stm32_Clock_Init(9); //初始化时钟
 delay_init(72);   //初始化延时
 uart_init(72,9600); //初始化串口 ///
 while(1)
  {
 printf("串口调试试验i自动加一 ");
 printf("i=%d ",i);
   i++;
   delay_ms(5000);
   if(i==20)
      i=2;
  }
}



#include "sys.h"
#include "usart.h"
////////////////////////////////////////////////////////////////////////////////// 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//Mini STM32开发板
//串口1初始化    
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2010/5/27
//版本:V1.3
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改说明
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//////////////////////////////////////////////////////////////////////////////////   
  //////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB  
#if 1
#pragma import(__use_no_semihosting)            
//标准库需要的支持函数                
struct __FILE
{
 int handle;
 /* Whatever you require here. If the only file you are using is */
 /* standard output using printf() for debugging, no file handling */
 /* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;      
//定义_sys_exit()以避免使用半主机模式   
_sys_exit(int x)
{
 x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{     
 while((USART1->SR&0X40)==0);//循环发送,直到发送完毕  
 USART1->DR = (u8) ch;     
 return ch;
}
#endif
//end
////////////////////////////////////////////////////////////////// #ifdef EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误    
u8 USART_RX_BUF[64];     //接收缓冲,最大64个字节.
//接收状态
//bit7,接收完成标志
//bit6,接收到0x0d
//bit5~0,接收到的有效字节数目
u8 USART_RX_STA=0;       //接收状态标记  
 
void USART1_IRQHandler(void)
{
 u8 res;    
 if(USART1->SR&(1<<5))//接收到数据
 { 
  res=USART1->DR;
  if((USART_RX_STA&0x80)==0)//接收未完成
  {
   if(USART_RX_STA&0x40)//接收到了0x0d
   {
    if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    else USART_RX_STA|=0x80; //接收完成了
   }else //还没收到0X0D
   { 
    if(res==0x0d)USART_RX_STA|=0x40;
    else
    {
     USART_RX_BUF[USART_RX_STA&0X3F]=res;
     USART_RX_STA++;
     if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收  
    }  
   }
  }                  
 }             
}
#endif          
//初始化IO 串口1
//pclk2CLK2时钟频率(Mhz)
//bound:波特率
//CHECK OK
//091209
void uart_init(u32 pclk2,u32 bound)
{   
 float temp;
 u16 mantissa;
 u16 fraction;   
 temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
 mantissa=temp;     //得到整数部分
 fraction=(temp-mantissa)*16; //得到小数部分 
    mantissa<<=4;
 mantissa+=fraction;
 RCC->APB2ENR|=1<<2;   //使能PORTA口时钟 
 RCC->APB2ENR|=1<<14;  //使能串口时钟
 GPIOA->CRH&=0XFFFFF00F;
 GPIOA->CRH|=0X000008B0;//IO状态设置
   
 RCC->APB2RSTR|=1<<14;   //复位串口1
 RCC->APB2RSTR&=~(1<<14);//停止复位       
 //波特率设置
  USART1->BRR=mantissa; // 波特率设置 
 USART1->CR1|=0X200C;  //1位停止,无校验位.
#ifdef EN_USART1_RX    //如果使能了接收
 //使能接收中断
 USART1->CR1|=1<<8;    //PE中断使能
 USART1->CR1|=1<<5;    //接收缓冲区非空中断使能      
 MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
#endif
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
33条回答
buenasdias1004
2019-08-18 17:15
今天也碰到了类似的问题,最终解决了,特地注册了个账号过来说一下。

我的情况是stm32F103和C8051F410通讯,两端用的都是485芯片。一开始出现的情况是C8051和电脑用485转串口的数据线可以通讯,STM32F103和电脑用该数据线也可以通讯(这里的通讯什么意思呢,就是没有乱码,所有的数据严丝合缝,发什么就接收到什么)。但是当直接把485的AA,BB连接起来后,就不能通讯了。(后来发现实际只是数据乱码,帧头帧尾检查不出了,所以以为通讯发生了异常。)

但两端都是同型号的485,为什么会发生这种现象呢?(其实这个我也 不知道)

看了上文,首先怀疑是电平的问题,我用示波器测试后。C8051F410通过串口发出的,是正负电平(就是大于0表示高电平1,小于0表示低电平0,幅值大概是正负5V),而电脑通过数据线发向STM32的,低电平实际上电压幅值在0.9V,高电平在5V左右),这就C8051F410和STM32两端485发送接收乱码的原因,于是,我把电路改了,C8051端的485输出端一端直接拉低,在用杜邦线连接两端485的时候,STM32和C51就通讯就正常了。

一周热门 更多>