最近做了一个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
//pclk2
CLK2时钟频率(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
}
那STM32输出可以设置为5V吗?
或者51是否又能设为3.3V ?
--------------------------------
没注意到C51板晶振是12MHz,换成11.0592MHz,能正常相互通信了。谢谢原子哥!
一周热门 更多>