FT232应用一问:
单片机PIC16F628A,采用FT232BL芯片,实现UART与COM通讯接口。1638为人机交互测试口,带数码管按键等,用于接收到数据的显示。程序用于测试接收,发送先不贴出来。执行结果为;发送一字节能有TX灯闪烁,然而无法启动接收,总是停留在检测起始位阶段。另外接收队列部分,也希望高手能解释一番。
程序清单:
#include
<htc.h>
#include "tm1638.h"
#define HITS 8
#define RXD_pin RA5
//定义MCU接收引脚,注意这里的倒置
#define TXD_pin RA2
//定义MCU发送引脚
#define RXD_pin_L TRISA5
//定义接收引脚
#define TXD_pin_L TRISA2
//定义发送引脚
#define RXD_BUF_LEN
32
//定义接收缓冲区大小
bank1 unsigned char RXD_buf[RXD_BUF_LEN];
//定义接收缓冲区(循环队列)
bank1 unsigned char RXD_p1, RXD_p2;
//指向缓冲区,由中断程序自动修改//指向缓冲区,由主程序修改
#define TXD_BUF_LEN
32
//定义发送缓冲区大小
bank1 unsigned char TXD_buf[TXD_BUF_LEN];
//定义发送缓冲区(循环队列)
bank1 unsigned char TXD_p1,TXD_p2;
//指向TXD_buf,由主程序修改//指向TXD_buf,由中断程序修改
//定义接收缓冲字符
bank1 unsigned char RXD_ch;
//定义发送缓冲字符
bank1 unsigned char TXD_ch,i;
//定义接收所需要的变量
static bit RXD_doing = 0;
//正在接收的标志
static unsigned int RXD_t = HITS/2;
//接收时计数T2的中断次数
static unsigned char RXD_cnt;
//接收时bit位的计数器
//定义发送所需要的变量
static bit TXD_doing = 0;
//正在发送的标志
static unsigned char TXD_t;
//发送时计数T2的中断次数
static unsigned char TXD_cnt;
//发送时bit位的计数器
unsigned char TEMP;
bit flag;
void T1_init(void)
{
GIE = 1;
PEIE=1;
TMR1IE = 1;
TMR1IF = 0;
//PT2 = 1;
//将T2中断设置成高级优先级
TMR1H =( 65536-65)%256;
TMR1L =( 65536-65)/256;
T1CON = 0x01; // 1分频 内部时钟 开启定时器
}
void RXD_init(void)
{
unsigned char i;
RXD_pin = 1;
RXD_p1 = 0;
RXD_p2 = 0;
for ( i=0; i<RXD_BUF_LEN; i++ )
{
RXD_buf = 0x00;
}
}
//
void TXD_init(void)
{
unsigned char i;
TXD_pin = 1;
TXD_p1 = 0;
TXD_p2 = 0;
for ( i=0; i< TXD_BUF_LEN; i++ )
{
TXD_buf = 0x00;
}
}
//发送单个字符
void TXD_Send_Char(const unsigned char c)
{
unsigned char p;
//临时变量
p = TXD_p1 + 1;
if ( p >= TXD_BUF_LEN ) p = 0;
while ( p == TXD_p2 );
//判断发送缓冲队列是否已满,如果是,则暂时不能发送
TXD_buf[TXD_p1] = c;
//先将c写入队列
TXD_p1 = p;
//再修改TXD_p1
//在T2中断服务程序里会自动完成发送
}
//发送字符串(不包括末尾的'\0')
void TXD_Send_String(const unsigned char s[])
{
unsigned char c;
unsigned int i = 0;
for (;;)
{
c = s[i++];
if ( c == '\0' ) break;
TXD_Send_Char(c);
}
}
void main(void)
{
unsigned char j,c;
RXD_pin_L=1;
TXD_pin_L=0;
flag=1;
for(j=0;j<100;j++)
delay(5000);
init_TM1638();
Write_COM(0x89);
Write_allLED(0xaa);
for(j=0;j<100;j++)
delay(5000);
TEMP=1;
T1_init();
TXD_init();
RXD_init();
while(1)
{
Write_DATA(7*2-2,tab[TEMP%16]);
Write_DATA(8*2-2,tab1[TEMP/16]);
if(TEMP>=255) TEMP=0;
if ( RXD_p2 != RXD_p1 )
{
c = RXD_buf[RXD_p2++];
if ( RXD_p2 >= RXD_BUF_LEN ) RXD_p2 = 0;
Write_DATA(1*2-2,tab[c%16]);
Write_DATA(2*2-2,tab[c/16]);
//
TXD_Send_Char(c);
}
}
}
//T1中断服务程序
//每中断HITS次处理1位
void interrupt T1INTSVC(void)
{
if(TMR1IF)
{
TMR1IE = 0;
TMR1IF = 0;
TMR1H =( 65536-65)%256;
TMR1L =( 65536-65)/256;
if ( RXD_doing )
//正处于接收状态
{
if ( --RXD_t == 0 )
//经过了HITS个采样脉冲
{
if ( RXD_cnt == 0 )
//8个数据位接收完毕
{
if ( RXD_pin )
//检测到停止位
{
RXD_t = RXD_p1 + 1;
//在这里,RXD_t作为临时变量
if ( RXD_t >= RXD_BUF_LEN ) RXD_t = 0;
if ( RXD_t != RXD_p2 )
//如果接收缓冲队列未满
{
RXD_buf[RXD_p1] = RXD_ch;
RXD_p1 = RXD_t;
}
else
{
//如果接收缓冲队列已满,只好丢弃新收到数据
}
}
else
//检测停止位时出错
{
//舍弃新收到的数据
}
RXD_doing = 0;
//接收全部完毕,清除正在接收的标志
RXD_t = HITS/2;
//恢复RXD_t的初始值
}
else
//接收数据位
{
RXD_ch >>= 1;
if(RXD_pin) RXD_ch=RXD_ch&0x01;
//上面2条语句若用{CY=RXD_pin; CY=(RXD_ch&0x01); RXD_ch=ACC;}代替,效率更高
RXD_cnt--;
RXD_t = HITS;
}
}
}
else
//检测起始位
{
if ( RXD_pin )
{
RXD_t = HITS/2;
TEMP++;
}
else
{
RXD_t--;
if ( RXD_t == 0 )
//连续HITS/2次采样RXD_pin都是0,就可以确认起始位
{
//启动接收
RXD_t = HITS;
RXD_cnt = 8;
RXD_doing = 1;
}
}
}
TMR1IE = 1;
}
} |