对于没有设计UART端口的系统来说通过利用 SWIM 端口输出调试信息是个很好很方便的方式,
不占用其它IO端口,就利用SWIM使用的IO口当作UART的TXD引脚输出调试信息。下面是在STM8L051上
实现的软件模拟UART的TXD引脚输出数据的示例。
/****************************************************************************|
文件:suart.c
IO口模拟UART发送数据功能模块
MCU :stm8l051f3
时钟:内部2MHz
作者:chipart.cn
声明:芯艺工作室 版权所有 COPYRIGHT 2018 chipart.cn
修改记录:
2018-11-24 创建
2019-10-24 移置到STM8L
*****************************************************************************/
#include "stm8l15x.h"
#include "stdio.h"
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#define F_CPU 2000000l
#define BAUD 9600
//模拟发送I/O端口操作定义(PB3:MOSI)
#define DEBUG_PORT_SET GPIOA->ODR|=(1<<0)
#define DEBUG_PORT_CLR GPIOA->ODR&=~(1<<0)
static volatile uint8_t g_EndFlag;//发送完成标记
static uint8_t g_SendCounter; //发送计数器
static uint8_t g_SendData; //发送数据
//功能初始化
void suart_init(void)
{
//定时器中断周期= f_cpu / baud (位时间)
CLK->PCKENR1 |= CLK_PCKENR1_TIM2;//TIM2定时器时钟允许
TIM2->ARRH = (F_CPU/BAUD)>>8;//自动装载值
TIM2->ARRL = (F_CPU/BAUD)&0XFF;
TIM2->PSCR = 0;//不分频
TIM2->CR1 = 0;//TIM_CR1_ARPE|TIM_CR1_CEN;//向上计数自动更新开始计数
TIM2->IER |= TIM_IER_UIE;//中断允许
//DEBUG_PORT_INIT
GPIOA->DDR|=(1<<0);
GPIOA->ODR&=~(1<<0);
GPIOA->CR1|=(1<<0);
GPIOA->CR2|=(1<<0);
DEBUG_PORT_SET; //默认状态为高
}
//定时器溢出中断处理函数
INTERRUPT void TIM2_IRQHandler (void)
{
TIM2->SR1 =0;
switch(g_SendCounter)
{
case 0: //开始位
DEBUG_PORT_CLR;
break;
case 9: //停止位
DEBUG_PORT_SET;
break;
case 10: //发送完成
TIM2->CR1=0;//计数器停止
g_EndFlag=1;//设置完成标记
break;
default: //数据
if(g_SendData&0x01)
DEBUG_PORT_SET;
else
DEBUG_PORT_CLR;
g_SendData>>=1;
break;
}
g_SendCounter++;
}
//发送一个字节
void suart_write_byte(uint8_t dat)
{
g_EndFlag=0;
g_SendCounter=0;
g_SendData=dat;
TIM2->CNTRH=0;
TIM2->CNTRL=0;
TIM2->CR1=TIM_CR1_ARPE|TIM_CR1_CEN;
while(g_EndFlag==0); //等待发送完成
}
//支持printf函数
PUTCHAR_PROTOTYPE
{
suart_write_byte(c);
}
GETCHAR_PROTOTYPE
{
return (0);
}
|
|