搜索
bottom↓
回复: 82

发个软件UART代码吧

  [复制链接]

出140入158汤圆

发表于 2016-2-17 17:17:03 | 显示全部楼层 |阅读模式
看到有位仁兄发帖用软件延时来模拟UART,实在惨不忍睹,看有人感兴趣,贴上8年前项目用的软件UART吧。


#include <iom32v.h>
#include <macros.h>

#include <string.h>

#include "Vga_drv.h"
#include "uart.h"
#include "Key_Scan.h"
#include "bmp.h"
#include "Isr.h"

#include "ps2_driver.h"

#include "eeprom.h"
#include "global.h"

#include "CRC.h"

#define uint32 unsigned long




#define SC_RXD 6
#define SC_RXD_SET_INPUT() {DDRD&=(~BIT(SC_RXD));}
#define SC_RXD_GET() ((PIND&(BIT(SC_RXD))))

#define SC_TXD 7
#define SC_TXD_0() {PORTD&=(~BIT(SC_TXD));}
#define SC_TXD_1() {PORTD|=BIT(SC_TXD);}
#define SC_TXD_SET_OUTPUT() {DDRD|=BIT(SC_TXD);}


uint8 sc1_rxd_scan_ct=0;
uint8 sc1_rxd_scan_next_time=0;
uint8 sc1_rxd_scan_step=0;
uint8 sc1_rxd_dat;
uint8 sc1_rxd_ready=0;
uint8 sc1_rxd_tmpdat;


uint8 sc_txd_ready=0;//模拟串口变量
uint8 sc_txd_bit_pt=0;
uint8 sc_txd_data=0;
uint8 sc_txd_ct=0;


void SC_Recv_Pro(uint8 dat){

}

void SC_RxdSrv(void){
       
        if(sc1_rxd_scan_step==0){
                if(!SC_RXD_GET()){
                        sc1_rxd_scan_step=1;
                        return;
                }
        }
        if(sc1_rxd_scan_step==1){
                if(!SC_RXD_GET()){
                        sc1_rxd_scan_step=2;                //rxd start bit ok,goto next step
                        sc1_rxd_scan_ct=0;
                        sc1_rxd_scan_next_time=3;
                        sc1_rxd_tmpdat=0;
                        return;
                }
                else{
                        sc1_rxd_scan_step=0;        //rxd start bit is avalid
                        return;
                }
        }
        if(sc1_rxd_scan_step>=2){
                sc1_rxd_scan_ct++;
                if(sc1_rxd_scan_ct<sc1_rxd_scan_next_time) return;
                sc1_rxd_scan_ct=0;
               
                if(sc1_rxd_scan_step<10){
                       
                        sc1_rxd_tmpdat>>=1;
                        if(SC_RXD_GET()){
                                sc1_rxd_tmpdat|=0x80;
                        }
                        sc1_rxd_scan_step++;       
                        return;
                }
                if(sc1_rxd_scan_step==10){
                        if(SC_RXD_GET()){
                                sc1_rxd_dat=sc1_rxd_tmpdat;
                                sc1_rxd_ready=1;

                                //Receive a byte OK       
                                #if 0
                                 sc_txd_data=sc1_rxd_dat;
                                 sc_txd_ready=1;
                                 #endif
                                 #if 0
                                 Test_Uart1(sc1_rxd_dat);
                                 #endif

                                 SC_Recv_Pro(sc1_rxd_dat);
                        }
                        sc1_rxd_scan_step=0;
                        return;
                }
               
               
        }

}



void SC_TxdSrv(void){
        sc_txd_ct++;
        if(sc_txd_ct<3) return;
        sc_txd_ct=0;
        if(sc_txd_ready){                                                        //Data Ready
                if(sc_txd_bit_pt<10){
                        if(sc_txd_bit_pt==0){
                                SC_TXD_0();                                //Start BIT
                       
                        }
                        else{
                               
                                if(sc_txd_bit_pt>=9){
                                        SC_TXD_1();                        //End BIT
                                }
                                else{                                                        //数据位
                                        if((sc_txd_data>>(sc_txd_bit_pt-1))&0x01){       
                                                SC_TXD_1();
                                        }
                                        else{
                                                SC_TXD_0();
                                        }
                                }                       
                        }
                }               
                if(sc_txd_bit_pt>10){               
                        sc_txd_bit_pt=0;                        //发送完后延时两个时钟,复位各标志
                        sc_txd_ready=0;               
                }
                else{
                        sc_txd_bit_pt++;                        //位指针自加               
                }
        }
       

}


void SC_send_char(uint8 b){
         sc_txd_data=b;
         sc_txd_ready=1;
         while(sc_txd_ready==1);

}
void SC_send_str(uint8 *str){
         while((*str)!=0){
                 SC_send_char(*str);
                str++;
         }

}


void init_SimComIO(void){
        SC_TXD_SET_OUTPUT();
        SC_TXD_1();

        SC_RXD_SET_INPUT();
}


#pragma interrupt_handler ISR_T1:8
void ISR_T1(void)
{
//compare occured TCNT1=OCR1A

        SC_RxdSrv();
        SC_TxdSrv();
}


阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出140入158汤圆

 楼主| 发表于 2016-2-17 17:19:56 | 显示全部楼层
把变量封装在结构体,在用结构体指针来访问,还可以无限扩展UART数量呢

出140入158汤圆

 楼主| 发表于 2016-2-17 17:29:50 | 显示全部楼层
曾经那这个代码(经过结构体封装的)跑过10个串口,在AVR上,当然波特率不高,4800bps。

出0入0汤圆

发表于 2016-2-17 19:18:18 | 显示全部楼层
只 用了一个定时器?

出0入0汤圆

发表于 2016-2-17 19:46:43 来自手机 | 显示全部楼层
多谢分享了,先收藏

出0入0汤圆

发表于 2016-2-17 20:23:14 | 显示全部楼层
SC_Recv_Pro函数是空的。楼主介绍下是如何设置定时,如何在主程序中调用的。打包个源工程,或者最简例程也好。期待中。

出0入4汤圆

发表于 2016-2-17 20:42:30 | 显示全部楼层
留个记号,还真有用得到的时候。谢谢!

出140入158汤圆

 楼主| 发表于 2016-2-17 20:57:06 | 显示全部楼层
bangbangji 发表于 2016-2-17 19:18
只 用了一个定时器?

对的,只用一个定时器,而且不影响定时器干其它事,波特率由定时中断的频率来决定,

出140入158汤圆

 楼主| 发表于 2016-2-17 20:58:04 | 显示全部楼层
upli 发表于 2016-2-17 20:23
SC_Recv_Pro函数是空的。楼主介绍下是如何设置定时,如何在主程序中调用的。打包个源工程,或者最简例程也 ...

就是接收完一个字节后中断调用的回调函数啊,想干嘛就干嘛咯

出140入158汤圆

 楼主| 发表于 2016-2-17 20:58:50 | 显示全部楼层
upli 发表于 2016-2-17 20:23
SC_Recv_Pro函数是空的。楼主介绍下是如何设置定时,如何在主程序中调用的。打包个源工程,或者最简例程也 ...

您就当它是串口的接收中断就得了

出0入0汤圆

发表于 2016-2-17 21:01:15 | 显示全部楼层
感谢,很好的代码,这模拟UART 非常实用的程序。

出75入90汤圆

发表于 2016-2-17 21:32:38 | 显示全部楼层
谢谢,正好在考虑要不要用软件模拟串口。

出140入158汤圆

 楼主| 发表于 2016-2-17 23:19:45 | 显示全部楼层
顺便说明一下,为了提高接收的准确率和纠错性能,采用3倍采样率,定时中断的频率是波特率的3倍。例如:需要波特率9600bps的话,需要1/(9600*3)=34.72us的定时中断。

出0入0汤圆

发表于 2016-2-18 07:49:09 来自手机 | 显示全部楼层
稳定性怎么样啊,曾经用过软件模拟,用的定时器中断模拟串口,飞思卡尔S12开两路CAN加两路LIN,在CAN100%负载率的时候模拟串口就容易出现错位,最后用输入捕捉和输出比较才解决的

出0入0汤圆

发表于 2016-2-18 08:14:10 | 显示全部楼层
mark....模拟串口。。。。。

出0入0汤圆

发表于 2016-2-18 08:20:46 | 显示全部楼层
mark下,休息时看看~~多谢楼主

出140入158汤圆

 楼主| 发表于 2016-2-18 11:49:22 | 显示全部楼层
q457344370 发表于 2016-2-18 07:49
稳定性怎么样啊,曾经用过软件模拟,用的定时器中断模拟串口,飞思卡尔S12开两路CAN加两路LIN,在CAN100%负 ...

稳定性非常的好,因为是3倍采样率,只要保证定时中断不被长时间打断即可保证通讯的稳定性

出0入0汤圆

发表于 2016-2-18 12:45:22 来自手机 | 显示全部楼层
关键就是被频繁打断,单片机主频16M,两路CAN100%负载率的时候每ms中断近10次,两路硬件串口每ms也要中断2次,另外还有个1ms的定时器中断,再加上一个捕捉中断

出140入158汤圆

 楼主| 发表于 2016-2-18 14:30:14 | 显示全部楼层
q457344370 发表于 2016-2-18 12:45
关键就是被频繁打断,单片机主频16M,两路CAN100%负载率的时候每ms中断近10次,两路硬件串口每ms也要中断2 ...

AVR没有硬件中断优先级,会比较呛

出0入0汤圆

发表于 2016-2-18 17:02:44 | 显示全部楼层
用这种对齐格/换行格式(好像有个专门的称呼,忘了。。。。)的都是异端!!!

非常凑巧的是,我也是这样对齐/换行。。。

出0入0汤圆

发表于 2016-2-18 19:02:32 | 显示全部楼层
优先级高的中断程序打断定时器中断,通讯是不是不能保证呀

出0入0汤圆

发表于 2016-2-18 21:35:44 | 显示全部楼层
amigenius 发表于 2016-2-18 14:30
AVR没有硬件中断优先级,会比较呛

刚看了下程序,只是为了稳定读起始位何必开3倍波特率呢,软件开销更大了

出140入158汤圆

 楼主| 发表于 2016-2-19 09:45:55 | 显示全部楼层
q457344370 发表于 2016-2-18 21:35
刚看了下程序,只是为了稳定读起始位何必开3倍波特率呢,软件开销更大了 ...

因为UART是异步,找到起始位的中点是关键,保证有足够的时序容差和稳定性,故开3倍采样率。其实每次进中断执行的就几行程序,CPU开销很小的。

出0入0汤圆

发表于 2016-2-19 12:37:42 来自手机 | 显示全部楼层
amigenius 发表于 2016-2-19 09:45
因为UART是异步,找到起始位的中点是关键,保证有足够的时序容差和稳定性,故开3倍采样率。其实每次进中 ...

这种方法做中断频繁的时候肯定没法用的,我刚开始用的是定时器中断加外部中断,进外部中断开1/2波特率定时器,关外部中断,定时中断到后检测是不是起始位,是就开1倍定时器中断接收数据。接收完一帧关定时器开外部中断,然后处理数据。所以在不收发数据时是不占用资源的。但是结果依然很容易被别的中断干扰,最后把方案换成用输入边沿捕捉接收,用输出比较发送。中断压力测试明显比定时器中断效果好

出0入0汤圆

发表于 2016-2-19 12:57:04 | 显示全部楼层
留着备用,谢谢LZ。

出0入0汤圆

发表于 2016-2-19 14:20:53 来自手机 | 显示全部楼层
q457344370 发表于 2016-2-19 12:37
这种方法做中断频繁的时候肯定没法用的,我刚开始用的是定时器中断加外部中断,进外部中断开1/2波特率定 ...

这位大侠的方法也很好,请问能共享个参考代码吗。

出140入158汤圆

 楼主| 发表于 2016-2-19 15:14:20 | 显示全部楼层
q457344370 发表于 2016-2-19 12:37
这种方法做中断频繁的时候肯定没法用的,我刚开始用的是定时器中断加外部中断,进外部中断开1/2波特率定 ...

没必要搞这么麻烦,软件串口占用中断的时间非常小,每次执行就几行程序,可以放在最高优先级中断。而且,我们设计程序结构时,占用时间长的程序段,是不会放在中断中处理的,这样才能保证中断的实时性,因为中断本来的意义就是处理需要实时响应的小段内容。如果您中断占用太多处理时间,那么您需要考虑您的程序结构了。

出0入0汤圆

发表于 2016-2-19 18:25:46 来自手机 | 显示全部楼层
amigenius 发表于 2016-2-19 15:14
没必要搞这么麻烦,软件串口占用中断的时间非常小,每次执行就几行程序,可以放在最高优先级中断。而且, ...

在18楼已经说了,程序上万行,ROM使用近100K,用16M再加上频繁中断感觉任何构架都白搭

出85入85汤圆

发表于 2016-2-19 19:03:48 来自手机 | 显示全部楼层
mark一下,以后细读

出0入0汤圆

发表于 2016-2-19 21:02:28 | 显示全部楼层
kation122 发表于 2016-2-19 14:20
这位大侠的方法也很好,请问能共享个参考代码吗。

程序在公司电脑上,没法外传,定时器中断的方法我已经说的很清楚了,捕捉中断原理就是先捕捉起始位(>=0.5Bit)然后把每次捕捉的时间四舍五入换算成nbit的0或1移进buff里,当检测移进去的位数大于等于接收1个字节需要的长度时说明接收完毕。大概就是这样,再把出错考虑进去就可以了

出0入0汤圆

发表于 2016-2-19 21:57:49 | 显示全部楼层
mark一下

出140入158汤圆

 楼主| 发表于 2016-2-20 09:16:03 | 显示全部楼层
q457344370 发表于 2016-2-19 18:25
在18楼已经说了,程序上万行,ROM使用近100K,用16M再加上频繁中断感觉任何构架都白搭 ...

那么用AVR就是一个错误。上万行的程序不算什么,我们程序经常是10多万行,4,5个UART,还要100K以上波特率,外加视频处理和图形界面,在72M的STM32跑的非常欢快,中断占用的时间非常小,当然,我们有硬件DMA。程序架构和优化非常的重要,别小看这个东西,我们以前有位女程序员,做个简单的空调程序,居然会吧中断用到阻塞,厉害吧。

出0入0汤圆

发表于 2016-2-20 09:28:57 | 显示全部楼层
多谢分享,正想着做这个

出0入0汤圆

发表于 2016-2-20 18:43:10 | 显示全部楼层
amigenius 发表于 2016-2-20 09:16
那么用AVR就是一个错误。上万行的程序不算什么,我们程序经常是10多万行,4,5个UART,还要100K以上波特 ...

用的是飞思卡尔,再说芯片选型不是我能管的,ST达到汽车级的只有SPC

出0入0汤圆

发表于 2016-3-2 19:34:59 | 显示全部楼层
我已经用楼主的代码在一个没有UART的51单片机上移植成功了,9600bps,运行流畅。特回头来答谢楼主!

出140入158汤圆

 楼主| 发表于 2016-3-2 20:25:11 | 显示全部楼层
upli 发表于 2016-3-2 19:34
我已经用楼主的代码在一个没有UART的51单片机上移植成功了,9600bps,运行流畅。特回头来答谢楼主! ...

恭喜!不客气。不过话说什么型号的51连个串口都没有这么寒酸

出0入0汤圆

发表于 2016-3-2 21:16:06 | 显示全部楼层
谢谢楼主,正需要这方面的资料呢

出0入0汤圆

发表于 2016-3-3 14:49:52 | 显示全部楼层
amigenius 发表于 2016-3-2 20:25
恭喜!不客气。不过话说什么型号的51连个串口都没有这么寒酸

自己公司开发的一个专用型MCU,纯粹为了测试验证的方便

出0入0汤圆

发表于 2016-9-21 15:16:42 | 显示全部楼层
谢谢楼主,之前模拟过接收,但是没有开启三倍采样~

出0入0汤圆

发表于 2016-9-23 08:19:34 | 显示全部楼层
好东西  感谢楼主分享  有机会试试

出0入0汤圆

发表于 2016-9-23 09:02:21 | 显示全部楼层
学习一下,看看程序的完善程度是否可以借鉴一下

出140入158汤圆

 楼主| 发表于 2016-9-23 09:32:31 | 显示全部楼层
小溪 发表于 2016-9-23 09:02
学习一下,看看程序的完善程度是否可以借鉴一下

稳定度可媲美硬件串口,而且可以无限扩展,只要CPU速度够,来50个串口也无问题。

出140入158汤圆

 楼主| 发表于 2016-9-23 09:33:37 | 显示全部楼层
要扩展多个的话,最好用结构体封装一下变量,访问时传递指针即可,程序会非常简洁。

出0入0汤圆

发表于 2016-10-24 16:24:23 | 显示全部楼层
本帖最后由 shjw 于 2016-10-24 16:30 编辑

三倍采样率,程序计时要乘以3?
怎么用结构体封装变量扩展串口

出140入158汤圆

 楼主| 发表于 2016-10-24 17:27:53 | 显示全部楼层
shjw 发表于 2016-10-24 16:24
三倍采样率,程序计时要乘以3?
怎么用结构体封装变量扩展串口

typedef sim_uart_def{
uint8 sc1_rxd_scan_ct;
uint8 sc1_rxd_scan_next_time;
uint8 sc1_rxd_scan_step;
uint8 sc1_rxd_dat;
uint8 sc1_rxd_ready;
uint8 sc1_rxd_tmpdat;
uint8 sc_txd_ready;//模拟串口变量
uint8 sc_txd_bit_pt;
uint8 sc_txd_data;
uint8 sc_txd_ct;
}TYPE_SIM_UART_DEF;

TYPE_SIM_UART_DEF su1,su2,su3,su4,su5,su6;

void SC_RxdSrv(TYPE_SIM_UART_DEF *pSU);
void SC_TxdSrv(TYPE_SIM_UART_DEF *pSU);

出0入0汤圆

发表于 2016-10-24 21:07:55 | 显示全部楼层
软UART,收藏备用。谢谢!

出0入0汤圆

发表于 2016-10-24 21:59:33 | 显示全部楼层
收藏了,用在其他协议应该也可以

出0入0汤圆

发表于 2016-10-25 08:40:52 | 显示全部楼层
mcu内核够快才行!

出0入0汤圆

发表于 2016-10-25 10:12:27 | 显示全部楼层
这个程序起始位搜索都没有使用中断捕获下降沿,直接用定时器中断来采样值,这样真的可以吗,两次采样低就是正确的起始位???如何理解

出140入158汤圆

 楼主| 发表于 2016-10-25 15:01:08 | 显示全部楼层
本帖最后由 amigenius 于 2016-10-25 15:03 编辑
myxiaonia 发表于 2016-10-25 10:12
这个程序起始位搜索都没有使用中断捕获下降沿,直接用定时器中断来采样值,这样真的可以吗,两次采样低就是 ...


三倍采样,检测到第一个下降沿,然后以第二个中断时间点作为采样点,以保证异步串口的时序容差,所以稳定性极佳,而且可以无限扩展。

出140入158汤圆

 楼主| 发表于 2016-10-25 15:07:02 | 显示全部楼层
外中断+定时器中断,优点是CPU占用相对少一点,但无办法用同样的硬件开销来扩展多个串口。而三倍采样,则无这个限制,以多一点点的CPU开销为代价(现在的CPU太快了,扩展十来个软件串口,毫无压力),换来无限的串口数。

出140入158汤圆

 楼主| 发表于 2016-10-25 15:09:21 | 显示全部楼层
wkman 发表于 2016-10-25 08:40
mcu内核够快才行!

51跑得很欢快,AVR无压力,Cortex更加毫无压力。

出0入0汤圆

发表于 2016-10-25 15:14:56 | 显示全部楼层
amigenius 发表于 2016-10-25 15:01
三倍采样,检测到第一个下降沿,然后以第二个中断时间点作为采样点,以保证异步串口的时序容差,所以稳定 ...

没看到啊,我看接收程序第一阶段先检测低电平,第二阶段如果还是低电平,认为是起始位,之后采样值就当作串口值,感觉好奇怪的样子
因为如果按照这之后采样值当串口位值看,这样采样率应该就是串口波特率,并没有3倍采样

从2次检测起始位的方法看,应该是认为完整的1位低电平时间就是起始位了,但是串口随时可以发送数据,不可能刚好就对齐到起始位的两个边界上,就算刚好对齐到完整1位的两个边界,也未必是起始位,也可能是刚好串口发送到某位是0值

出140入158汤圆

 楼主| 发表于 2016-10-25 15:51:59 | 显示全部楼层
myxiaonia 发表于 2016-10-25 15:14
没看到啊,我看接收程序第一阶段先检测低电平,第二阶段如果还是低电平,认为是起始位,之后采样值就当作 ...

三倍采样的目的是准确找到起始位0的中点,然后以这个作为基准时间来采样往后的8位,以确保时序容差,避开各个位的交界点,使之准确接收数据而不产生误码。

出0入0汤圆

发表于 2016-10-25 16:05:32 | 显示全部楼层
q457344370 发表于 2016-2-19 12:37
这种方法做中断频繁的时候肯定没法用的,我刚开始用的是定时器中断加外部中断,进外部中断开1/2波特率定 ...

捕捉肯定好些 不过有些没捕捉功能就是。

出0入0汤圆

发表于 2016-10-25 22:13:44 | 显示全部楼层
amigenius 发表于 2016-10-25 15:51
三倍采样的目的是准确找到起始位0的中点,然后以这个作为基准时间来采样往后的8位,以确保时序容差,避开 ...

终于看明白了,第一步搜索起始位中心点,这一步还是非常巧妙的

不过第二次确定的采样点如果非常接近下一个位起始点的话,相当于你的3倍采样无效了

出140入158汤圆

 楼主| 发表于 2016-10-26 08:44:52 | 显示全部楼层
myxiaonia 发表于 2016-10-25 22:13
终于看明白了,第一步搜索起始位中心点,这一步还是非常巧妙的

不过第二次确定的采样点如果非常接近下一 ...

大哥您是一位非常严谨的人,敬佩!其实4倍采样可完全确保,不过CPU开销变大了,模拟的串口数不很多时可采用。实际使用时发现3倍采样,已经非常稳定,所以没做4倍采样。为了规避3倍采样踩到边界的风险,我以前做多串口时还加入了一个技巧,就是如果在多串口的时候,在扫描完各个串口IO之后,再回扫一次,是否有1到0的跳变,如果有,则置该串口的sc1_rxd_scan_step=1,这样采样点又回到位的中点了。

出0入0汤圆

发表于 2016-10-26 14:22:05 | 显示全部楼层
   标记以下

出0入0汤圆

发表于 2016-11-1 21:56:44 | 显示全部楼层
标记一下,最近在用模拟串口

出0入0汤圆

发表于 2016-11-2 08:52:16 | 显示全部楼层
模拟串口 收藏

出0入0汤圆

发表于 2017-1-11 11:21:47 | 显示全部楼层
顶一下,用起来                        

出140入158汤圆

 楼主| 发表于 2017-1-11 12:24:07 | 显示全部楼层
WM_CH 发表于 2017-1-11 11:21
顶一下,用起来

这个代码其实很好用的,反正我自己用在很多项目上,无任何问题

出0入0汤圆

发表于 2017-2-20 10:15:33 | 显示全部楼层
学习学习

出0入0汤圆

发表于 2017-2-21 14:33:43 | 显示全部楼层
学习了,我一般就模拟一下IIC,SPI等

出0入10汤圆

发表于 2017-2-21 17:20:00 | 显示全部楼层
好好研究一下!感谢楼主分享。

出0入0汤圆

发表于 2017-3-1 18:30:35 | 显示全部楼层
好帖不会沉!

出0入0汤圆

发表于 2017-3-1 21:10:05 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2017-11-7 19:51:43 | 显示全部楼层
谢谢楼主分享,非常好用的代码

出0入0汤圆

发表于 2018-1-3 15:48:53 | 显示全部楼层
这个好!!谢谢。用在产品中,非常稳定

出40入18汤圆

发表于 2018-1-21 16:45:49 | 显示全部楼层
又学习到了一个实用知识

出0入14汤圆

发表于 2018-1-21 23:02:59 | 显示全部楼层
amigenius 发表于 2016-2-20 09:16
那么用AVR就是一个错误。上万行的程序不算什么,我们程序经常是10多万行,4,5个UART,还要100K以上波特 ...

感觉你也是汽车电子行业的?用哪个STM32哪个芯片能做视频处理?能处理 RGB    CVBS?

出0入14汤圆

发表于 2018-1-21 23:12:28 | 显示全部楼层
本帖最后由 isakura 于 2018-1-21 23:16 编辑

看到这个帖子想到了以前的一个想法

原来以前一直在找那种8脚甚至是更小的单片机,只需要具有串口功能的,一直没找到
发现很多小封装的都有SPI功能,可是没有串口功能,很奇怪

现在想起来可以模拟(原来觉得模拟的不稳定,就没多考虑),

最近也做了一个类似的定时器模拟通讯,不过用的是STM32F105,这个定时器牛逼,都做到了几us的通讯,而且挺稳定的

不过老款的小封装单片机,像飞思卡尔那些,容量一两K的,估计主频不高,不知道波特率能到多少

出0入42汤圆

发表于 2018-4-22 16:31:11 | 显示全部楼层
谢谢楼主无私分享,最近刚好要用到

出0入0汤圆

发表于 2018-4-22 16:54:36 | 显示全部楼层
软UART,收藏备用。谢谢!

出0入0汤圆

发表于 2018-4-30 07:35:44 | 显示全部楼层
如果波特率用115200,能否稳定模拟3个UART?估计能模拟2个也很有难度

出130入0汤圆

发表于 2018-4-30 08:43:14 来自手机 | 显示全部楼层
无限扩展,NB

出0入0汤圆

发表于 2018-4-30 08:52:29 来自手机 | 显示全部楼层
标记一下,备用

出0入4汤圆

发表于 2018-4-30 09:13:16 来自手机 | 显示全部楼层
用外部中端+定时器,或捕捉+定时输出,对cpu的占用都相对较小。但是模拟最大的缺点是如果cpu halt掉比如擦写flash就挂了

出0入0汤圆

发表于 2018-4-30 16:57:21 来自手机 | 显示全部楼层
标记!仔细学习一下

出0入0汤圆

发表于 2018-4-30 17:05:28 | 显示全部楼层
nb,学习了,多谢,正好需要

出0入0汤圆

发表于 2019-5-9 23:35:02 | 显示全部楼层
收藏了多谢啊

出0入0汤圆

发表于 2019-5-10 08:04:24 | 显示全部楼层
收藏,mark下......

出0入0汤圆

发表于 2019-5-10 10:07:30 | 显示全部楼层
amigenius 发表于 2016-2-17 23:19
顺便说明一下,为了提高接收的准确率和纠错性能,采用3倍采样率,定时中断的频率是波特率的3倍。例如:需要 ...


我是假装来学习的。。定时器是最宝贵的资源。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 22:42

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表