INT0和INT1口发送和接收数据

2019-07-15 16:58发布

通过INT0发送一堆数据,比如有“00 11 22 33 44 55”,然后进入芯片中。芯片传回数据,通过INT1接收数据。
这个用什么实现呢?不太懂中断啊。有个思路什么的不
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
Aidaohuakai
1楼-- · 2019-07-15 18:41
楼主的意思就是相当于模拟一个串口,发送的话用普通IO口就可以了,接受的话用外部中断。
模拟 UART 非常简单,一条 IO 模拟发送的 TX,一条 IO 模拟接收的 RX,另外将地 GND 引出就可
以实现 UART 功能。在硬件上基本不用考虑太多,只需要注意 IO 口上下拉电阻的选择,如果 IO 口内部可以选择设置上下拉电阻,必须设为上拉电阻,如果 IO 口不提供内部上下拉电阻控制最好在外部连上 10k~51k 的上拉电阻。有了上拉电阻,就可以确保 TX 能可靠输出高低电平,RX 即使没有和另外的设备相连也能保证读到的状态是 1,这样是为了和 UART 通讯时序中用 1 来表示空闲的要求一致。
要用 IO 软件模拟 UART,就需要用软件在 IO_TX 脚输出满足 UART 通讯时序的波形,还能检测出IO_RX 脚上的波形是否与 UART 通讯时序一致并将数据正确读回。UART 可以设置成多种工作状态,“9600/8/N/1”表示波特率为 9600,这个速率收发一个位大约耗时 104us,8 位数据位,无校验位,1 位停止位。IO_TX 的控制比较简单,先将对应 IO 设置成输出,然后输出 1 表示当前没有数据发送。当需要发送数据的时候,先输出一个 104us 宽的低电平做为起始位 0,然后按 104us/位的宽度按照先低位后高位的顺序依次输出所发数据的各个位,最后将输出 104us 宽的高电平做为停止位 1。这样一个字节的发送过程就全部完成,如果还有数据需要发送,按同样的方法操作即可。IO_TX 发送过程最关键的地方是保证每个位宽为 104us。最简单的方法是用代码实现延时,在
发送过程中最好关闭所有中断以保证延时准确。如果不想去数代码有多少周期也可以用定时中断来实现,让单片机产生一个 104us 的定时中断,然后在中断程序被调用后的同一时刻依次输出所有位,这个定时中断需要最高的优先级,否则其它中断会导致时间不准。 IO_RX 的控制要复杂一些,将对应 IO 设置成输入,然后需要让程序不停的检测 IO_RX 上有没有收到 0,一旦检测到 0 则表示一个数据开始传送,需要启动接收过程。接收程序最好是 IO_RX 刚从1 变为 0 就能立刻检测到,这样才能保证接收过程 104us 间隔的时间基点准确。
检测数据开始传送的方法基本上为这三种:
①  IO_RX 支持负跳变触发中断用中断检测。(外部中断)
②  程序用不超过 52us 的定时中断程序定时检测。
③  程序在主程序中循环检测。
这三种方法中负跳变中断的方法最好,时间基点可以控制得非常准,后两种方法时间基点误差相对都比较大。检测到 IO_RX 从 1 变为 0 后就需要严格按照通讯时序来读取数据的各个位,我个人认为最好的方法如下:
①在检测到数据开始传送后 26us/52us/78us 三个点读 IO_RX状态,要求这三点必须全为 0,否则错误退出。
②然后在 52+104*N us 位置读得 8 个数据位。
③再在 104*9+26us/52us/78us 三个点读 IO_RX 状态,要求这三点必须全为 1,否则错误退出。
●注:计算时间需要将中断响应时间考虑进去
不管是 IO_TX 还是 IO_RX,实际上都很难准确无误的做到 104us 的延时间隔,如果延时和绝对
时间两者间误差达到一定限度时,就会出错,这里示意了 IO_RX 延时不够大的情况。那为什么①和③需要做一个 26us/52us/78us 的特殊处理呢?来看看我们发送 0xFF 时候的波形,这个波形很简单,就是一个宽度为 104us 的负脉冲。以 104us 间隔去读数据,我们可以正确读回 0xFF,但果以 52us 的间隔去读,我们会读到一个 0xFE。所以认为能读到数据就万事大吉,所读到的结果并不一定正确。反过来也一样,如果发送方改为以 4800 波特率(208us 间隔)发送 0xFF,接收方以 9600 波特率接收会误读到 0xFE。
那为什么只在 26us/52us/78us 三点处理而不是在整个宽度内尽可能多次的判断呢?是因为我们日常应用中波特率不随意定的,前人已经选择了一些常用的波特率做为标准,这些波特率是 300/600/1200/2400/4800/…,它们间大多数呈现两倍的关系,26us/52us/78us 三点已经能将相邻的波特率检测出来。读的次数过多的话还会带来另外一个麻烦,那就是每个设备和绝对波特率时间间隔之间或多或少都会存在一定误差,也就是波特率9600的基准间隔大约104us,实际中的设备和这个间隔都存在一定误差,误差大的甚至 103us 和 105us都有可能出现,如果读太多的话会让这个误差允许范围变得非常小,所以不要去读太多次,留足够的间隔来容纳误差。 那到底可以接受多大的误差呢?10 个位总宽度为 1040us,如果不做 26us/52us/78us 的特殊处理,最后读停止位的时间应该是1040-52=988us,当延时间隔偏小时我们只要保证到这个点大于104*9=936us 就行,也就是负偏差最大可以到(936/988-1)*100%=5.2%,考虑到收发双方都会存在误差,所以能接受的误差还要除以 2 为 2.6%,实际应用中一般认为 3%以内都可以被接受。用 IO 模拟 UART 会有一些限制:首先是对高波特率的模拟难以实现;其次是在收发数据的时候为了保证时间间隔的精准会影响其它中断的使用;另外如果想能收发同时进行(全双工)需要比较
高的程序技巧。如果编程语言不是汇编而是 C,去数指令周期数会比较麻烦,如果想偷懒的话就是关掉中断用示波器将延时调准。
  最佳答案
shanshushan0
2楼-- · 2019-07-15 22:36
首先INT0和INT1是对于外部信号触发而言的,所以它们都应该是输入,所以没有通过INT0发送数据这一说吧。。你可以把这个引脚当做普通的I/O口来发送数据啊,为什么要涉及到中断呢?至于用INT1接收数据,这个倒是可以考虑一下使用中断。
开心就好240615
3楼-- · 2019-07-16 03:42
INT0和INT1是虽然可也作为一般的I/O接口用,但一般都用其第二功能,也就是外部中断。第一功能和第二功能是在不同条件下用的,不能说又作为一般的I/0接口,又作外部中断的触发引脚。

一周热门 更多>