登录 免费注册 首页 | 行业黑名单 | 帮助
维库电子市场网
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统
驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe

寻找软串口的源代码

作者:luya 栏目:单片机
寻找软串口的源代码
 
2楼: >>参与讨论
luya
软串口
 
3楼: >>参与讨论
winhiwang
有人刚发过,你查一下
 
4楼: >>参与讨论
jcsasm
什么叫软串口??
 
5楼: >>参与讨论
luya
大多是用汇编写的,请问有没有用C51写的呢?
 
6楼: >>参与讨论
maychang
老古网上有
 
7楼: >>参与讨论
雁舞白沙
LPC932 软串口 1200
void INT_INT0(void) interrupt 0
{
    unsigned CHAR BitData;
    bit BitChk;
    EA=0;
    EX0=0;
    WDT();
    EX0=0;
    BitData=0;
    BitChk=1;
    SeriesInData=0;
    Delay(130);                          //等过起始位
       while(BitData<9)
       {         
           if(BitData==8)
        {
            SeriesBitNine=RXD;
        }
           if(RXD==1)
           {
               SeriesInData|=0x0080;
            BitChk=~BitChk;
           }           
          BitData++;
          if(BitData<8)
        {
            SeriesInData>>=1;
        }          
          Delay(90);
       }
    if(BitChk)
    {
        if(ComEn)
        {
            ComBit=1;
            SeriesSt=0;
        }
        else
        {
            ComEn=1;
            ComBit=1;
            SeriesSt=1;
        }
        
        
    }
    EX0=1;
    EA=1;
}

void DataCom(void)
{
    if(ComBit)
    {
        //串口数据集合校验
        if(ComEn)
        {
           if(SeriesSt)
           {
               if(SeriesBufDptr<60)
                  {
                   if(SeriesBufDptr==0)            //数据缓冲区地址指针是否为零
                   {                                   
                       if(SeriesInData==0x68)            //缓冲区的第一个数据是否等于0x68*/
                       {
                           ComDataBuf[0]=SeriesInData;    //数据保存到缓冲区*/
                              SeriesBufDptr++;        //缓冲区地址累加*/
                       }
                       else
                       {
                           SeriesBufDptr=0;
                       }
                   }
                   else
                   {
                        ComDataBuf[SeriesBufDptr]=SeriesInData;    //数据保存到缓冲区*/
                        SeriesBufDptr++;                    //缓冲区地址累加*/
                   }
               }
               else
               {
                   SeriesBufDptr=0;
               }
               if(SendOverFg)
               {
                  if(ComDataBuf[ComDataBuf][9]+11]==0x16)
              &nb
8楼: >>参与讨论
hotpower
厉害
 
9楼: >>参与讨论
luya
太好了!还没有看呢,先赞一下!!
很感谢!

10楼: >>参与讨论
雁舞白沙
什么厉害?
 
11楼: >>参与讨论
xymxym
!!!
我最近用T2和INT两个中断模拟了串口,效果还不错,摘出里面的一部分供你参考


#include "reg52.h"
#include <intrins.h>

#define uCHAR unsigned CHAR
#define uint unsigned int

#define StartBit 0
#define EndBit 9

#define N 10
    
     sbit F_Receive = P3^2;

     uCHAR data AUX_Count,AUX_Time,AUX_State,AUX_Mode,AUX_Temp;
     uCHAR data AUX_Buf[N];
     bit AUX_Received,AUX_En;


void T_Rece(void) interrupt 2
{                                  //INT2中断
     AUX_Time = 11;                
     if (!AUX_En)
     {                             //开始接收数据串的准备工作
          AUX_Count = 0;          //接收字节数初始
          AUX_State = 1;                 //假设现在为为起始位,则下一次应该指向数据的第一位
          AUX_Received = 0;              //整个数据串接收完毕,此位置1
          AUX_Buf[0] = 0x00;             //接收缓冲区初始
          AUX_En = SET;                  
     
          T2High = SysBpsH;
          T2Low = SysBpsL;               //填入要模拟的串口的波特率位时间,由T2进行中断
          TH2 = T2High;
          TL2 = T2Low;
          TF2 = 0;
          TR2 = SET;
          ET2 = SET;                     //启动T2进行计数的中断
          PT2 = SET;                     //T2为最高权
     }
}

void Time2(void) interrupt 5
{
     
     TH2 = T2High;              //定时器2每隔bps秒中断,作为模拟串口的位时间
     TL2 = T2Low;
     TF2 = 0;

     if (--AUX_Time != 0)
     {                            //位数减一
          if (AUX_State == StartBit)
          {                      //现在的中断刚好落在起始位状态,不作任何处理
               AUX_State++;      //只将状态指向数据态
          }
          else if (AUX_State == EndBit)
          {                       //现在是终止位状态,
               AUX_State = StartBit;   //将接收的状态指向起始位,准备下一个数据的接收
               AUX_Buf[AUX_Count++] = AUX_Temp;  //将接收的字节数据存入数组
               AUX_Temp = 0x00;
          }
          else
          {
               AUX_Temp >>= 1;            //不是起始位也不是终止位的状态,那只能是数据位了
               if (F_Receive)
                    AUX_Temp |= 0x80;
               ++AUX_State;               //接收状态指向下一态
          }
     }
     else
     {                   //如果计满11位的时间,AUX_Time未再被重置,说明数据串已接收完毕
          EX1 = SET;
          IE1 = CLR;
          
          TR2 = CLR;
          ET2 = CLR;
          PT2 = CLR;
        
          AUX_En = CLR;
          AUX_Received = SET;    //该位置1,在主程序中查询并调用子程序对所接收的数据处理
     }
}

12楼: >>参与讨论
luya
万分感谢!
 
13楼: >>参与讨论
tianle1010
我给你发一个,希望你有用~~
//******************************************************************************
// MSP-FET430X110 DEMO - Timer_A UART Ultra-low POWER 2400 Echo, 32KHZ ACLK
//
// DESCRIPTION: Use timer_A CCR0 HARDWARE OUTPUT modes and SCCI data latch to
// to implement UART function @ 2400 baud. SOFTWARE does not directly read and
// write to RX and TX pins, instead proper use of OUTPUT modes and SCCI data
// latch are demonstrated. Use of these HARDWARE features eliminates ISR
// latency effects as HARDWARE insures that OUTPUT and input bit latching and
// timing are perfectly synchronised with timer_A regardless of other
// SOFTWARE activity. In the Mainloop the UART function readies the UART to
// receive one CHARacter and waits in LPM3 with all activity interrupt driven.
// After a CHARacter has been received, the UART receive function forces exit
// from LPM3 in the Mainloop which echo's BACK the received CHARacter.
// ACLK = TACLK = LFXT1 = 32768, MCLK = SMCLK = DCO ~ 800K
// //*An external watch CRYSTAL is required on XIN XOUT for ACLK*//
//
// MSP430F1121
// -----------------
// /|\| XIN|-
// | | | 32KHZ
// --|RST XOUT|-
// | |
// | CCI0A/TXD/P1.1|-------->
// | | 2400 8N1
// | CCI0B/RXD/P2.2|<--------
//
#define RXD 0x04 // RXD on P2.2
#define TXD 0x02 // TXD on P1.1

// Conditions for 2400 Baud SW UART, ACLK = 32768

#define Bitime_5 0x06 // ~ 0.5 bit length + small adjustment
#define Bitime 0x0E // 427us bit length ~ 2341 baud

unsigned int RXTXData;
unsigned CHAR BitCnt;

void TX_Byte (void);
void RX_Ready (void);

// M.Buccini
// Texas Instruments, Inc
// September 2003
// Built with IAR Embedded Workbench Version: 1.26B
// January 2004
// Updated for IAR Embedded Workbench Version: 2.21B
//******************************************************************************


#include <msp430x11x1.h>

void main (void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
CCTL0 = OUT; // TXD Idle as Mark
TACTL = TASSEL_1 + MC_2; // ACLK, continuous mode
P1SEL = TXD; // P1.1/TA0 for TXD function
P1DIR = TXD; // TXD OUTPUT on P1
P2SEL = RXD; // P2.2/TA0 as RXD input

// Mainloop
for (;;)
{
RX_Ready(); // UART ready to RX one Byte
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr until CHAR RXed
TX_Byte(); // TX BACK RXed Byte Received
}
}


// Function Transmits Character from RXTXData Buffer
void TX_Byte (void)
{
BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
while (CCR0 != TAR) // Prevent async capture
CCR0 = TAR; // Current state of TA counter
CCR0 += Bitime; // Some time till first bit
RXTXData |= 0x100; // Add mark stop bit to RXTXData
RXTXData = RXTXData << 1; // Add space start bit
CCTL0 = OUTMOD0 + CCIE; // TXD = mark = idle
while ( CCTL0 & CCIE ); // Wait for TX completion
}


// Function Readies UART to Receive Character into RXTXData Buffer
void RX_Ready (void)
{
BitCnt = 0x8; // Load Bit counter
CCTL0 = SCS + CCIS0 + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge, Cap
}


// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
CCR0 += Bitime; // Add Offset to CCR0

// RX
if (CCTL0 & CCIS0) // RX on CCI0B?
{
if( CCTL0 & CAP ) // Capture mode = start bit edge
{
CCTL0 &= ~ CAP; // SWITCH from capture to compare mode
CCR0 += Bitime_5;
}
else
{
RXTXData = RXTXData >> 1;
if (CCTL0 & SCCI) // Get bit waiting in receive latch
RXTXData |= 0x80;
BitCnt --; // All bits RXed?
if ( BitCnt == 0)
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
{
CCTL0 &= ~ CCIE; // All bits RXed, disable interrupt
_BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR)
}
//>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
// TX
else
{
if ( BitCnt == 0)
CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt
else
{
CCTL0 |= OUTMOD2; // TX Space
if (RXTXData & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
RXTXData = RXTXData >> 1;
BitCnt --;
}
}
}

14楼: >>参与讨论
luya
十分感谢!
 
15楼: >>参与讨论
luya
请问雁舞白沙
请问,雁舞白沙,你的波特率是如何设制的?

16楼: >>参与讨论
luya
请您把变量定义也发给我好么,这样更可读一些。多谢
 
17楼: >>参与讨论
雁舞白沙
倒数的关系
luya ;请问雁舞白沙 ,你的波特率是如何设制的?

雁:延时---1200的倒数


18楼: >>参与讨论
yang96381
哈哈,我详细说一下原理
以51单片机为例,晶振采用12M,波特率9600,1位起始位,8位数据位,1位停止
位,采用P1口中的任意两只引脚,如果接收采用中断方式,那么还得用一个外部
中断0或1引脚,用来检测负跳变的起始位!!! 波特率9600的倒数为104微秒,
这就是发送1位所需的时间,每隔104微秒发送1位数据,因为采用I/O口模拟串口,所以对软件延时十分严格,否则所发送或接收的数据误码大。适当减少波特
率可减少误差。
   采用这种方法适合发送或接收少量的数据!!!

19楼: >>参与讨论
lql441
IO口模拟232通讯程序占用定时器0,晶振为11.0592MHZ
/**********************************************

IO口模拟232通讯程序占用定时器0,晶振为11.0592MHZ

**********************************************/

#include <at89x51.h>

sbit TX =P1^0;
sbit RX =P1^1;

#define TIMER0_ENABLE  TL0=TH0; TR0=1;
#define TIMER0_DISABLE TR0=0;
volatile bit  F_TM;

void IntTimer0() interrupt 1
{
F_TM=1;
}
/*发送一个字符*/
void SendChar(unsigned CHAR inch)
{
unsigned CHAR i;
i=0;
F_TM=0;
TX=0; //start bit
TIMER0_ENABLE; //启动
while(!F_TM);

while(i<8)
{
   if(inch&1)//数据由低位到高位发送
   {
    TX=1;
   }
   else
   {
    TX=0;
   }
   F_TM=0;
   while(!F_TM);
   i++;
   inch>>=1;
  }
  TX=1;
  F_TM=0;
  while(!F_TM);
  TIMER0_DISABLE; //停止timer
}

/*接收一个字符*/
unsigned CHAR ReceChar()
{
unsigned CHAR rch,i;
TIMER0_ENABLE;
F_TM=0;
i=0;
rch=0;
while(!F_TM); //等过起始位

while(i<8)
{
  rch>>=1;
  if(RX)
  {
   rch|=0x80; //数据从低位到高位接收
  }
  i++;
  F_TM=0;
  while(!F_TM);
}
F_TM=0;
while(!F_TM)
{
  if(RX)
  {
   break;
  }
}
TIMER0_DISABLE; //停止timer
return rch;
}

/*检查是不是有起始位*/
bit StartBitOn()
{
return  (RX==0);
}

void main()
{
TMOD=0x22;    //定时器1为工作模式2(8位自动重装),0为模式2(8位重装)
PCON=0x00;
TR0=0;        //在发送或接收才开始使用
TF0=0;
TH0=(256-96); //9600bps 就是1000000/9600=104.167微秒 执行的timer是104.167*11.0592/12= 96//
TL0=TH0;
ET0=1;
EA=1;
while(1)
{
  SendChar('e');
}
}


20楼: >>参与讨论
luya
多谢各位!!
yang96381说的很明白,我今天下午看了一个网上下载的程序也有同样的体会,多谢热心人!

参与讨论
昵称:
讨论内容:
 
 
相关帖子
开个各种单片机的优缺和近4年内的市场论谈!
那位编写过温度IC LM74的程序?
C51编程:问一个关于51外存问题
4-20mA信号的隔离方法有哪些?
关于DS18B20的问题
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入


Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号