把LPC900的串口模拟程序移植到了LPC922,很稳定 yuzhuju 发表于 2005-6-14 11:49 Philips LPC900单片机 感觉LPC900写的程序可读性很好,不像有些网友的C语言里面都偏僻语法,看上去好象很高深厉害,实际可读性一点都不好.第一次用模拟串口,感觉收发很稳定,谢谢LPC900. /*用I/O模拟串行口例程(LPC900) 下面的程序是我以前写的,适合于80C52内核的单片机,不能直接用在LPC900系列单片机上。我现在懒了, 不想再修改,如果要用,您自己动手做一些修改吧: 首先,该程序中的定时器用的是T2,然而LPC900系列单片机中没有T2。您可以将其换成T0或者是T1。 RXD_pin和TXD_pin的属性要重新做一些设置,使之能够在您的LPC900单片机上运行。 晶振不能用22.1184MHz那么高,建议用低于12MHz的晶振或者直接使用片内RC振荡器。*/ /* 52单片机实用的IO模拟串行口C语言源程序 作者:LPC900 移植: saint(yuzhuju) 用途:短距离、波特率要求不高、环境干扰不大的场合 特点: 程序简练、实用、移植方便 占用定时器T0 只消耗约600字节的ROM 有详细的注释 参数: 晶振 :7.373MHz 波特率:2400 起始位:1 数据位:8 校验位:无 停止位:1 ----------------------- yuzhuju: 感觉程序中的HITS只有在判断开始位时,才有实际意义, 其它HITS使用场合中,如果不是每次采样都和上次结果作比较判断,意义就不是很大,只能凑个接收周期 不知道理解对不对. -----------------------*/ extern void Uart2Init(void);//初始化extern void TXD_Send_String(const unsigned char s[]);//发送字符串函数extern void Uart2Task(void);//放在主函数WHILE(1)中,一旦收到结束符号'?',把RXD_buf中收到的数据发送回来 #i nclude <REG922.H> //修改如下定义将方便程序移植sbit RXD_pin = P0^4; //定义接收引脚sbit TXD_pin = P0^5; //定义发送引脚#define MAIN_CLK 7373000 //定义主频#define BAUD_RATE 2400 //定义波特率(数值不能太高,因为要给T2中断服务程序留足执行时间)#define HITS 8 //定义采样率(应当是偶数;减少采样率能提高波特率,但为保证可靠工作,最小不能少于6次) #define RXD_BUF_LEN 16 //定义接收缓冲区大小volatile unsigned char RXD_buf[RXD_BUF_LEN]; //定义接收缓冲区(循环队列)volatile unsigned char RXD_p1; //指向缓冲区,由中断程序自动修改volatile unsigned char RXD_p2; //指向缓冲区,由主程序修改 #define TXD_BUF_LEN 16 //定义发送缓冲区大小volatile unsigned char TXD_buf[TXD_BUF_LEN]; //定义发送缓冲区(循环队列)volatile unsigned char TXD_p1; //指向TXD_buf,由主程序修改volatile unsigned char TXD_p2; //指向TXD_buf,由中断程序修改volatile bit U2TEnable; //定时器T0初始化void Time0Init(void){ unsigned char TimeValue; TAMOD&=(~0x01);//T0M2=0 TMOD|=0X02;//T0M1=1 TMOD&=(~0X01);//T0M0=0,T0 MODE 2 TMOD&=(~0X04);//设置为定时器功能; TMOD&=(~0X08);//设置为TR0使能定时器 IP0H|=0x02;//设置T0为最高优先级中断 IP0|=0x02; TimeValue=256 - ( MAIN_CLK / 2 ) / ( BAUD_RATE * HITS ); //此公式值得你琢磨一下 //好象只能设置到2400,再低就要溢出了 TH0 = TimeValue; TL0 = TimeValue; ET0= 1; TR0 = 1;} //接收初始化void RXDInit(void){ unsigned char i; P0M1 &= ~(0X01 << 4); //PortSet(0,4,GPIO);把P0.4设置为GPIO P0M2 &= ~(0X01 << 4); RXD_pin = 1; RXD_p1 = 0; RXD_p2 = 0; for(i=0;i<16;i++)//RXD_BUF_LEN { RXD_buf[i] = 0x00; }} //发送初始化void TXDInit(void){ unsigned char i; P0M1 &= ~(0X01 << 5); //PortSet(0,5,GPIO);把P0.5设置为GPIO P0M2 &= ~(0X01 << 5); TXD_pin = 1; TXD_p1 = 0; TXD_p2 = 0; for ( i=0; i< TXD_BUF_LEN; i++ ) {TXD_buf[i] = 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); }} //定义接收缓冲字符volatile unsigned char bdata RXD_ch;sbit RXD_ch_MSB = RXD_ch^7; //定义发送缓冲字符volatile unsigned char bdata TXD_ch;sbit TXD_ch_LSB = TXD_ch^0; //T2中断服务程序//每中断HITS次处理1位static void IRQTIME0() interrupt 1 using 3{//定义接收所需要的变量 static bit RXD_doing = 0; //正在接收的标志 static unsigned char 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位的计数器//先清除TF2 TF0 = 0;//接收数据 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; if(RXD_ch=='?'){U2TEnable=1;} } else { //如果接收缓冲队列已满,只好丢弃新收到数据 } } else //检测停止位时出错 { //舍弃新收到的数据 } RXD_doing = 0; //接收全部完毕,清除正在接收的标志 RXD_t = HITS/2; //恢复RXD_t的初始值 } else //接收数据位 { RXD_ch >>= 1; RXD_ch_MSB = RXD_pin; //上面2条语句若用{CY=RXD_pin; CY=(RXD_ch&0x01); RXD_ch=ACC;}代替,效率更高 RXD_cnt--; RXD_t = HITS; } } } else //检测起始位[/#] { if ( RXD_pin ) { RXD_t = HITS/2; } else { RXD_t--; if ( RXD_t == 0 ) //连续HITS/2次采样RXD_pin都是0,就可以确认起始位 { //启动接收 RXD_t = HITS; RXD_cnt = 8; RXD_doing = 1; } } }//发送数据 if ( TXD_doing ) //正处于发送状态 { TXD_t--; if ( TXD_t == 0 ) { if ( TXD_cnt == 0 ) //发送全部完毕 { TXD_doing = 0; //清除正在发送的标志 } else { if ( TXD_cnt == 1 ) //8个数据位发送完毕 { TXD_pin = 1; //发送停止位 } else //发送数据位 { TXD_pin = TXD_ch_LSB; TXD_ch >>= 1; //上面2条语句若用{CY=(TXD_ch&0x01); TXD_pin=CY; TXD_ch=ACC;}代替,效率更高 } TXD_cnt--; TXD_t = HITS; } } } else { if ( TXD_p2 != TXD_p1 ) //如果发送缓冲队列不空 { //从发送缓冲队列中取出要发送的数据 TXD_ch = TXD_buf[TXD_p2++]; if ( TXD_p2 >= TXD_BUF_LEN ) TXD_p2 = 0; //启动发送 TXD_doing = 1; TXD_cnt = 9; TXD_t = HITS; //先发送起始位 TXD_pin = 0; } else { //发送缓冲队列是空的,不发送任何数据 } }} //系统初始化void Uart2Init(void){ TXDInit(); RXDInit(); Time0Init(); U2TEnable=0;} void Uart2Task(void){ unsigned char c; if(U2TEnable) { while ( RXD_p2 != RXD_p1 ) { c = RXD_buf[RXD_p2++]; if ( RXD_p2 >= RXD_BUF_LEN ) RXD_p2 = 0; TXD_Send_Char(c); } TXD_Send_String("Return Data Over.\r\n"); U2TEnable=0; }} //主程序void main(void){ Uart2Init(); TXD_Send_String("The author is 21IC LPC900.\r\n"); { Uart2Task(); } }

评论