注:本博客作为学习笔记,有错误的地方希望指正
问题:串口和定时器不能同时使用的问题
解决方法:
1、注意配置TMOD 的时候 要加上与运算给,不然就会改变该定时器的的在定时器的寄存器的值,后面定时器配置就会覆盖串口中使用到的定时器的TMOD 的状态值
2、其次还要在接收串口的数据的时候关闭EA,关闭全局中断,防止接收消息的时候被中断打断,不过51单片机有自己中断优先级管理的,不像STM32自己可以规定中断优先级的。
好的,介绍完毕,上菜(Code)
1、主函数 初始化定时器和串口配置,主循环中检测电机运行状态
#include "STC8051.h"
#include "Uart.h"
#include "Common.h"
#include "Motor_86.h"
#include <intrins.h>
/**********************************************************************************
函数名称:main()
功能描述:主函数.
参数说明:无
返回说明:无
其他说明:无
***********************************************************************************/
void main(void)
{
Uart_Init();
Motor_86_init();
while(1)
{
Motor_86_Run();
}
}
2、串口配置 Uart.c 配置串口的基本参数 和中断接收的判断处理
#include "STC8051.h"
#include "Common.h"
#include "Uart.h"
#include "Motor.h"
#include "Motor_86.h"
#include <string.h>
//#define STC12C5A60S2 //条件编译决定使用12系列MCU
#define Fosc 11059200 //晶振
#define Band 9600 //波特率
extern char Run_Flag;
U8 Tmp;
bit flag = 0;
/**********************************************************************************
函数名称:Uart_Init()
功能描述:完成对串口配置初始化
参数说明:无
返回说明:无
其他说明:无
***********************************************************************************/
void Uart_Init(void)
{
#ifdef STC12C5A60S2
AUXR = 0x15; //1T
BRT = 256 - Fosc/Band/32; //波特率计算公式
SM0 = 0;
SM1 = 1; //工作方式
REN = 1; //允许接收
PCON = 0x00; //SMOD=0
ES = 1; //使能串口中断
EA = 1; //使能总中断
#else //STC89C52系列MCU
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
SM0 = 0;
SM1 = 1; //设置有定时器控制波特率的工作方式1
REN = 1; //串行口允许接受数据
ES = 1; //使能串口
PCON = 0x00; //波特率倍增不使能
EA = 1;
#endif
}
/**********************************************************************************
函数名称:UartIntServe()
功能描述:串口中断,用于监控上位机发送指令,收到什么数据就发送回什么数据
参数说明:无
返回说明:无
其他说明:无
***********************************************************************************/
void UartIntServ(void) interrupt 4
{
if (RI==1) //判断是否接受完一个字节数据
{
EA = 0; //关闭中断
Tmp = SBUF; //接收数据
Massage_state = ~Massage_state;
if(Tmp == 0x01) //系统启动 -> 安卓界面 "运行"
{
Run_Flag = 1; //运行标志设置为1
ET0 = 1; //打开定时器
}
else if(Tmp == 0x02) //加速(延时减少) -> 安卓界面 "加速"
{
Speed -= 10;
if(Speed <= 10) //向下溢出
Speed = 10;
}
else if(Tmp == 0x03) //减速(延时增多) -> 安卓界面 "减速"
{
Speed += 10;
if(Speed >= 250) //向下溢出
Speed = 250;
}
else if(Tmp == 0x04) //暂停系统 -> 安卓界面 "停转"
{
Run_Flag = 0; //运行标志设置为1
ET0 = 0; //关闭定时器
Puse =0; //脉冲端口拉低
}
else if(Tmp == 0x05) //暂停正转 -> 安卓界面 "正转"
{
Run_Dir = 1; //方向标志设置为1
}
else if(Tmp == 0x06) //暂停反转 -> 安卓界面 "反转"
{
Run_Dir = 0; //方向标志设置为0
}
RI=0; //接收标志位清零
EA = 1; //开启中断
}
}
2.1 Uart.h 基本配置
#ifndef __UART_H__
#define __UART_H__
#define U8 unsigned char //字符型
#define U16 unsigned int //整型
#define U32 unsigned long //长整型
extern U8 Tmp;
extern bit flag;
//UART 相关函数------------------------
extern void Uart_Init(void);
//UART----END-------------------------------
#endif
3、电机函数配置(定时器0配置)
#include "Motor_86.h"
#include "STC8051.h"
unsigned int timer1; //运行计数
int Speed = 5; //运行速度
char Run_Flag = 0; //是否运行标志
char Run_Dir = 0; //运行方向标志
unsigned char i=0;
void delay_ms(unsigned int i)
{
unsigned char j;
for(i; i > 0; i--) //循环 600*255 次
for(j = 255; j > 0; j--);
}
/*********************************************
* 函数名称:Motor_86_init
* 函数功能:步进电机初始化
* 参 数:无
* 说 明:无
**********************************************/
void Motor_86_init(void)
{
EA = 1; //打开总中断
TR0 = 1; //打开定时器0中断
ET0 = 0; //关闭定时器0
TH0=(65536-5000)/256; //给time0装初值
TL0=(65536-5000)%256;
TMOD|=0x02; //设置定时器t0的工作方式
}
/*********************************************
* 函数名称:Motor_86_Dir_Contol
* 函数功能:步进电机的方向控制
* 参 数:dir dir=0 反方向 dir=1 正方向
* 说 明:无
**********************************************/
void Motor_86_Dir_Contol(char dir)
{
if(dir == 0)
{
DIR = 0;
}
else if(dir == 1)
{
DIR = 1;
}
}
/********************************************
* 函数名称:Motor_86_Run
* 函数功能:步进电机运行控制
* 参 数:无
* 说 明:无
*********************************************/
void Motor_86_Run(void)
{
if(Run_Flag == 1) //只有在系统启动后才具有加速,减速和正转,反转的..
{
if(Run_Dir == 1) //正方向运行
{
Motor_86_Dir_Contol(1);
}
else if(Run_Dir == 0) //反方向运行
{
Motor_86_Dir_Contol(0);
}
}
else
{
delay_ms(500); //没有运行空延时等待事件的发生
Run_state = 0;
delay_ms(500); //没有运行空延时等待事件的发生
Run_state = 1;
}
}
/********************************************
* 函数名称:Motor_86_Time
* 函数功能:定时器中断
* 参 数:无
* 说 明:无
*********************************************/
void time0(void) interrupt 1 using 0
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
timer1++; //计数+1
if(timer1>=Speed)
{
Puse =0;
}
else
{
Puse =1;
}
if(timer1 >= 250)
{
timer1 = 0;
}
}
3.1电机函数头文件配置
#ifndef _Motor_86_H_
#define _Motor_86_H_
#include "STC8051.h"
sbit DIR = P1^0; //步进电机方向引脚 0.0
sbit Puse = P1^3; //步进电机脉冲引脚 0.1
sbit Run_state = P1^1; //状态显示
sbit Massage_state = P1^2; //消息接收显示
extern int Speed;
extern unsigned int timer1;
extern char Run_Flag;
extern char Run_Dir;
void delay_ms(unsigned int i);
void Motor_86_init(void);
void Motor_86_Dir_Contol(char dir);
void Motor_86_Run(void);
#endif
4、历程解说视频:源码分析