STC15单片机串口打印

实现功能

1.上电时,通过TTL转USB接口输出系统启动信息

2.运行时,间隔100ms输出hello字符串和一个自动加1的变量

STC15L2K32S2型号串口配置

串口的使用跟之前STC89C52的一样,只不过这个型号具有两个串口,都是UART(通用异步收发器),分别在两组不同的引脚上

串口1建议放在[P3.6/RxD_2,P3.7/TxD_2]或[P1.6/RxD_3/XTAL2,P1.7/TxD_3/XTAL1]上。

寄存器的配置可用STC-ISP软件生成,也可根据手册进行配置,最后记得打开中断

程序

文件结构

main.c ->主函数文件,包含main函数等;

Public.c ->公共函数文件,包含Delay延时函数等;

Sys_init ->系统初始化函数,包含GPIO初始化函数等;

LED.c->LED外设函数,包含LED打开、关闭函数等;

Timer0.c ->定时器函数,包含定时器初始化,中断函数等;

KEY1.c->按键1函数,包含按键检测,中断函数等;

KEY2.c ->按键⒉函数,包含按键状态机检测函数等;

PWM. c ->PWM初始化、亮度调节、占空比储存与恢复函数等;

IAP.c->字节读、字节写、扇区擦除等函数。

UART1.c->串口1初始化、发送、中断等函数。

UART.h:

主要是定义波特率的枚举类型,之前用串口都是程序写死波特率,要改的话又要用软件生成一次,这次的灵活点,定义该波特率枚举类型后在后面可以用switch语句列出这四种波特率的TH1、TL1的初始值,在使用时,直接修改波特率的变量的值即可,非常方便

然后就是定义接口类型的枚举,再对串口的结构体进行定义,函数指针是等UART.c里的函数实现后,把名字复制过来的

#ifndef __UART_H_
#define __UART_H_//定义波特率的枚举类型
typedef enum
{Band_4800   = (uint8_t)0,Band_9600   = (uint8_t)1,Band_19200  = (uint8_t)2,Band_115200 = (uint8_t)3
}BandRate_t;//定义接口类型的枚举类型
typedef enum
{TTL     = (uint8_t)0,RS_485  = (uint8_t)1,RS_232  = (uint8_t)2
}Interface_Type_t;//定义异步通信串口结构体类型
typedef struct
{BandRate_t        ucBandRate;         //波特率uint8_t volatile  ucTX_Busy_Flag;     //发送忙碌标志uint8_t volatile  ucRec_Flag;         //接收标志位uint8_t volatile  ucRec_Cnt;          //接收计数uint8_t *pucSend_Buffer;            //发送缓存指针uint8_t *pucRec_Buffer;             //接收缓存指针void (*UART_Init)();                        //串口初始化void (*UART_SendData)(uint8_t);             //串口发送字符void (*UART_SendArray)(uint8_t*,uint16_t);  //串口发送数组void (*UART_SendString)(uint8_t *);         //串口发送字符串void (*Protocol)();                         //接口协议uint8_t Interface_Type;                     //接口类型void (*RS485_Set_SendMode)();               //RS-485接口设置为发送模式void (*RS485_Set_RecMode)();                //RS-485接口设置为接收模式}UART_t;/* extern variables-----------------------------------------------------------*//* extern function prototypes-------------------------------------------------*/ #endif
/********************************************************End Of File
********************************************************/

UART1.h:

主要是先宏定义后续会学到的RS-485接口的单片机引脚,然后就把UART.h中的结构体变量声明为外部变量

#ifndef __UART1_H_
#define __UART1_H_//串口引脚宏定义
#define UART1_TX  P37       //这两个引脚接到RS-485
#define UART1_RX  P36/* extern variables-----------------------------------------------------------*/
extern UART_t idata UART1;
/* extern function prototypes-------------------------------------------------*/ #endif
/********************************************************End Of File
********************************************************/

UART1.c:

与串口相关的分别是4个函数,串口初始化,串口发送字符,串口发送数组,串口发送字符串,另外对putchar函数进行重写,实现printf函数的重定向,为什么这里修改putchar函数而不是fputc函数,可以看之前的的文章(串口打印-printf重定向)

/* Includes ------------------------------------------------------------------*/
#include <main.h>/* Private define-------------------------------------------------------------*/
#define UART1_Send_LENGTH 20
#define UART1_Rec_LENGTH  10
/* Private variables----------------------------------------------------------*/
static uint8_t idata ucSend_Buffer[UART1_Rec_LENGTH]  = {0};
static uint8_t idata ucRec_Buffer[UART1_Rec_LENGTH]   = {0x00};
/* Private function prototypes------------------------------------------------*/
static void Init();                                 //串口初始化
static void SendData(uint8_t dat);                  //串口发送字符
static void SendArray(uint8_t *p_Arr,uint16_t LEN); //串口发送数组
static void SendString(uint8_t *p_Str);             //串口发送字符串
static void Protocol();                             //串口协议static void RS485_Set_SendMode();                   //RS-485设置为发送模式
static void RS485_Set_RecMode();                    //RS-485设置为接收模式/* Public variables-----------------------------------------------------------*/
UART_t idata UART1 =
{Band_115200,FALSE,FALSE,0,ucSend_Buffer,ucRec_Buffer,Init,SendData,SendArray,SendString,Protocol,TTL,RS485_Set_SendMode,RS485_Set_RecMode
};/*
* @name   Init
* @brief  串口1初始化
* @param  None
* @retval None
*/
static void Init()
{//串口1默认映射至P30,P31,因为切换寄存器AUXR1上电默认值为0x00,默认串口1在P3.0和P3.1SCON = 0x50;       //8位数据,可变波特率,REN位置1,开启中断//辅助寄存器AUXR的第6位T1x12置1,设置定时器1的速度是传统8051的12倍,不分频AUXR |= 0x40;//1111 1110 最低位S1ST2清0,选择定时器1作为串口1的波特率发生器AUXR &= 0xFE;        //串口1选择定时器1为波特率发生器TMOD &= 0x0F;        //设定定时器1为16位自动重装方式switch (UART1.ucBandRate){case Band_4800:   TL1 = 0xCD; TH1 = 0xFD; break;case Band_9600:   TL1 = 0xE0; TH1 = 0xFE; break;case Band_19200:  TL1 = 0x70; TH1 = 0xFF; break;case Band_115200: TL1 = 0xE8; TH1 = 0xFF; break;default:          TL1 = 0xCD; TH1 = 0xFD; break;}ET1 = 0;        //禁止定时器1中断TR1 = 1;     //启动定时器1
}/*
* @name   SendData
* @brief  发送字符
* @param  dat:待发送的数据
* @retval None
*/
static void SendData(uint8_t dat)
{while(UART1.ucTX_Busy_Flag);    //等待前面的数据发送完,串口中断中发送数据后标志位会置FALSEUART1.ucTX_Busy_Flag = TRUE;    //置为忙碌标志位SBUF = dat;                     //写数据到UART寄存器
}/*
* @name   SendArray
* @brief  发送数组
* @param  p_Arr:数组首地址,LEN:发送长度
* @retval None
*/
static void SendArray(uint8_t *p_Arr,uint16_t LEN)
{uint16_t i = 0;for(i = 0;i<LEN;i++){UART1.UART_SendData(*(p_Arr+i));}while(UART1.ucTX_Busy_Flag);
}/*
* @name   SendString
* @brief  发送字符串
* @param  p_Arr:字符串首地址
* @retval None
*/
static void SendString(uint8_t *p_Str)
{while(*(p_Str) != '\0'){UART1.UART_SendData(*(p_Str++));}while(UART1.ucTX_Busy_Flag);
}/*
* @name   RS485_Set_SendMode
* @brief  RS_485接口设置为发送模式
* @param  None
* @retval None
*/
static void RS485_Set_SendMode()
{}/*
* @name   RS485_Set_RecMode
* @brief  RS_485接口设置为接收模式
* @param  None
* @retval None
*/
static void RS485_Set_RecMode()
{}/*
* @name   putchar
* @brief  字符发送函数重定向
* @param  c:发送的字符
* @retval char
*/
extern char putchar(char ch)
{UART1.UART_SendData((uint8_t)ch);   //在putchar函数内直接调用串口发送字符函数return ch;
}/*
* @name   UART1_isr
* @brief  串口1中断处理函数
* @param  None
* @retval None
*/
void UART1_isr() interrupt 4
{if(RI){RI = (bit)0;                   //清除接收中断标志/*UART1_Rec_LENGTH宏定义为10,所以接收的数据不能超过10个字节UART1.ucRec_Cnt表示数组下标,初始化为0*/if(UART1.ucRec_Cnt < UART1_Rec_LENGTH){ucRec_Buffer[UART1.ucRec_Cnt++] = SBUF;}UART1.ucRec_Flag = TRUE;      //接收完成标志位}if(TI){TI = (bit)0;                    //清除发送中断标志UART1.ucTX_Busy_Flag = FALSE;   //清除忙碌标志}
}/*
* @name   Protocol
* @brief  串口协议
* @param  None
* @retval None
*/
static void Protocol()
{}
/********************************************************End Of File
********************************************************/

看教学时需要注意的地方

1.在串口协议中,奇偶校验位用的不多,一般用CRC校验,在Modbus总线中会有介绍

2.收发双方的比特率要一致

3.串口通信时,STC-ISP软件尽量选择外部时钟,因为内部时钟受环境因素影响比较大,会导致波特率发生偏差,会有不稳定现象

4.发送数组的函数中形参指针不能++,所以改为+i;如果将形参赋给另一个指针,那指针就可++

5.printf打印重定向:首先main.h中添加头文件< stdio.h >,然后Usart1.c中修改putchar函数,内部调用串口发送字符函数,然后main.c主函数中使用printf(“xxx:%d”,xxx)通过串口打印数据

STC15单片机-串口打印相关推荐

  1. STC15单片机-串口打印printf重定向

    printf函数重定向为往串口打印信息 在UART.h.UART1.h和UART.c文件的内容编写好后,在main函数中实现通过串口发送一串字符串和一个不断加1的变量 方法一: 使用sprintf函数 ...

  2. DIY单片机串口打印函数print

    原始的单片机串口只能发送单字节数据,再加个封装也就能发送个字符串,但是无法发送数字变量,要发送数字变量那基本要引入C语言的库函数printf,但是这个pintf函数 好用确实是好用但是有个很大的缺点相 ...

  3. STM32软件学习笔记(一)基于HAL库的STM32F429单片机串口打印程序

    |版权声明:本文为博主原创文章,转载请注明出处.https://blog.csdn.net/NeverImagine_/article/details/95517664   目前ST官方有提供两种库文 ...

  4. 51单片机串口打印函数

    51单片机串口通信调试printf函数重定向输出打印 1.首先需要实现串口的发送和接收. 2.输出printf需要哪些步骤: 1)需要引入头文件 <stdio.h> 2)添加如下代码: c ...

  5. 51单片机串口打印不管是中文还是英文都是乱码的问题

    讲道理都tm大三暑假了还搞51单片机而且关键是还遇到了一个问题解决了一天才解决出来真的是很丢人了. 不过我会珍惜这个机会的,毕竟这有可能是我辈子最后一次跟着老师搞这个破玩意了. 好了不废话了 收! 昨 ...

  6. STC15W408AS单片机通过ADC端口采集模拟量并从串口打印数值

    STC15W408AS单片机通过ADC端口采集模拟量并从串口打印数值 0-1023数据采集 STC15W408AS引脚功能图 STC15系列单片机的A/D转换器 A/D转换器的结构 STC15系列单片 ...

  7. 【STC15】STC15单片机获取红外解码从软串口输出

    [STC15]STC15单片机获取红外解码从软串口输出 单片机型号:STC15F2K60S2 采用外部晶振,频率:11.0592MHz 红外接收头,数据引脚接P3.2 这里软串口实现主要是位处理时间一 ...

  8. 使用单片机的串口打印功能

    转载请注明出处 个人看法,仅供分享 单片机调试手段: 1.在线调试 部分芯片支持该功能,典型的有STM32系列的SWD接口,沁恒的CH32V和CH32F系列.CH56X部分RISC-V的两线调试. 2 ...

  9. 51单片机 DHT11温湿度传感器LCD显示+串口打印显示

    第一部分:DHT11详解: DHT11是一款有已校准数字信号输出的温湿度传感器. 精度湿度±5%RH, 温度±2℃,量程湿度20-90%RH, 温度0~50℃. **一.电路连接分析 1.引脚图** ...

  10. 8位单片机只用一个定时器T0进行红外解码,包括短按、长按处理,模拟串口打印数据

    最近自己在网上搜了很多资料,发现很多的红外解码,关于重码的处理的代码很少,分享一下红外解码包括重码的处理. 使用单片机:EN8F156 功能说明:红外遥控器解码,只使用定时器T0定时100us进行按键 ...

最新文章

  1. 网页开发 与数据联动的图_零基础学习数据可视化pyecharts人物关系图开发
  2. python多线程之threading
  3. 怎么控制latex插图的位置_如何在报告OR论文中画出漂亮的插图?
  4. c web mysql数据库_C连接Mysql数据库代码
  5. 地图漫游功能的具体体现_【漫游天下】赣南 | 悠扬风韵之都
  6. MySQL高级知识(十)——批量插入数据脚本
  7. python turtle绘制七段数码管日期时间(注释)
  8. 开发者点评GitHub 暗黑模式:太暗了
  9. java遍历字符串_Java后端开发算法基础面试题分享,你离大厂也许就差这份面试题
  10. ssh集群服务器免密登录
  11. java连接池hkai,MySQL连接配置文件密码加密及其在多种连接池上的应用
  12. android 商米扫码sdk,商米收银机|外接扫码枪问题:以T2为例
  13. CPU基础---设计一个8位的并行加法器
  14. 【转载】原生Ajax写法
  15. 大数据行业包含的岗位有哪些
  16. mysql建库图解_MySQL数据库安装图解
  17. dev c++怎么设置断点_linux操作系统引导与启动——内核启动和初始化(二)断点...
  18. Linux入门参考文档(超详细)
  19. TCP的TIME_WAIT状态为什么要等待2MSL的时长
  20. 关于神舟笔记本TX8连副屏经常蓝屏的问题

热门文章

  1. 可孚医疗的数字化突围
  2. a4在html中的尺寸,网页设立A4大小
  3. mysql varchar 长度设置_Mysql中varchar长度设置方法
  4. 《人类的演化》读书笔记
  5. android应用流程图,Android APP 启动流程简析
  6. 打开DOSbox时设置指定虚拟路径
  7. 弘辽科技:淘宝保证金解冻后店铺还在吗?保证金怎么解冻?
  8. cos(a-b)=cosa*cosb+sina*sinb的推导过程
  9. HackMyvm(九)Gigachad持续更新
  10. python处理xps文件_xps/pdf/png/json转换