IO模拟串口之中断方式发送(后台运行?)
2019-11-15 来源:51hei
#include
//内部振荡器4M,看门狗关,上电复位延时,开外部复位脚,数据保护关,代码保护关,关掉电复位
__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF); //12F675
#define uchar unsigned char
#define uint unsigned int
#define TX GP0
#define RX GP1
#define KEY GP2
#define R_S GP4
#define LED GP5
uchar TX_REG,T_TMP;
bit TX_IF;
void delay_ms(uint wm) //进入退出一次8个指令周期
{
uchar i;
for(;wm!=0;wm--)
{
i=163;
while(i--);
NOP();
NOP();
}
}
/*
模拟串口,定时器中断发送方式,波特率9600
*/
void UART(uchar U_D)
{
while(T0IE); //等待上一次数据发送完毕
TMR0=175; //预充值
TX=0; //发送起始位
T0IF=0; //清零定时器中断
T0IE=1; //定时器0中断使能
TX_REG=U_D; //转移数据到发送缓存
T_TMP=8; //预置需要发送的位个数(8位数据)
TX_IF=1; //数据发送完毕标志
}
void init()
{
CMCON = 0b00000111; //关闭内部比较器
ANSEL = 0; //全部为数字IO
TRISIO = 0b00001110; //设置RA0为TX,RA1为RX,RA2为IRQ,RA3为复位,RA4为,RA5为
GPIO = 0b00000001; //
OPTION_REG=0b00001110;//GPIO上拉,TMR0时钟为内部
WPU = 0b00001110;
INTCON = 0b11000000;
}
void main(void)
{
init();
while(1)
{
if(KEY==0)
{
delay_ms(100);
if(KEY==0)
{
UART('O');
UART('K');
UART('r');
UART('n');
}
}
}
}
void interrupt INT()
{
if(T0IF) //检测到定时器0中断
{
TMR0=169; //预充值
if(T_TMP) //检测数据是否发送完毕
{
TX=TX_REG; //输出数据
TX_REG>>=1; //移位数据
--T_TMP; //
}
else //发送完毕后进行停止位发送
{
if(TX_IF)
{
TX=1;
TX_IF=0;
}
else
{
T0IE=0; //发送完毕后关闭定时器中断
}
}
T0IF=0;
}
}
以上程序为定时器中断方式IO模拟串口,
优点就是占用CPU少(只使用一次子函数后一直等待定时器中断才处理一次),
缺点是占用一个定时器