OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3957|回复: 49

求路过的大哥指点下,卡在这点上一个多月了,一直调试有问题!

[复制链接]

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
发表于 2019-1-3 13:31:10 | 显示全部楼层 |阅读模式
小弟最近在做一款芯片,用的是STM8S003的芯片做的,根据客户定制给的通讯协议接收外部信号特定的字节,然后写入eerpom中,现在主要是协议复位吗没办法识别,求高手指点下,谢谢!小弟用的是串口接收的,串口设置的是9位数据(+1位停止位)-250K的波特率,通讯协议也是按到9位数据(+1位停止位)-250K的波特率这样来的,目前就是对这个2S复位码没办法具体识别出来!
麻烦看到的给个指点,感激不尽!
EOGNWI0O0}28B6FZKEP(9@G.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

231

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2872
金钱
2872
注册时间
2018-1-24
在线时间
258 小时
发表于 2019-1-3 13:57:27 | 显示全部楼层
用定时器加外部中断来解析可能好一点
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-4 09:59:43 | 显示全部楼层
9位数据,250K波特率,有点像是DMX信号,参考一下DMX信号解码......
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-5 13:26:28 | 显示全部楼层
spritels 发表于 2019-1-4 09:59
9位数据,250K波特率,有点像是DMX信号,参考一下DMX信号解码......

是跟DMX信号一样的,但是不同的是,我既要接收DMX信号,还要接受这个,DMX信号这个break是88-1S时间,这个是大于2S,所以我对这2个做判断的时候一直区别不出来,还请大哥能解惑下,谢谢
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-5 13:28:07 | 显示全部楼层
bebj2009 发表于 2019-1-3 13:57
用定时器加外部中断来解析可能好一点

不太明白,是在串口接收中断中启动定时器吗?麻烦解惑下,感谢
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-8 09:02:26 | 显示全部楼层
通常我们做DMX解码是不判断这个break的长度的,而是判断第九位数据来确定是不是数据头.不知道你这个信号数据包的第九位是什么特点,如果是类似,可以考虑这么来.
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-12 13:37:02 | 显示全部楼层
spritels 发表于 2019-1-8 09:02
通常我们做DMX解码是不判断这个break的长度的,而是判断第九位数据来确定是不是数据头.不知道你这个信号数据 ...

完全跟DMX解码一样,第9位是一样的,和DMX协议不一样的地方就是这个break时长变成2S了
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-12 13:54:04 | 显示全部楼层
胡松松 发表于 2019-1-12 13:37
完全跟DMX解码一样,第9位是一样的,和DMX协议不一样的地方就是这个break时长变成2S了

大哥还是比较热情,如果方便的话,希望加个好友,帮忙一起交流下,指点下小弟,感谢                邮箱 770510477@qq.com
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-21 13:14:37 | 显示全部楼层
求帮忙顶置,有愿意指点的请给小弟帮忙下,小弟愿意有偿感谢!
回复 支持 反对

使用道具 举报

2

主题

41

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
419
金钱
419
注册时间
2014-7-30
在线时间
263 小时
发表于 2019-1-24 13:05:38 | 显示全部楼层
本帖最后由 503126063 于 2019-1-24 13:11 编辑

可以利用 帧错误,我用N76E003试过用 帧错误来做LIN通信。
检测到 帧错误进入中断时,再用定时器计数,或者用输入捕获(硬件上RX与一路输入捕获并在一起)来解码复位信号
TIM图片20190124130425.png
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-24 14:38:55 | 显示全部楼层
503126063 发表于 2019-1-24 13:05
可以利用 帧错误,我用N76E003试过用 帧错误来做LIN通信。
检测到 帧错误进入中断时,再用定时器计数,或 ...

谢谢大哥帮忙指点,我之前也用想过,但是如果我在串口接收中断里面开启定时器定时,这样串口中断会不会和定时器中断冲突,我在接受数据的同时还可以进入定时器中断计数吗?
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-24 16:54:01 | 显示全部楼层
如果单纯是识别你要求的这个信号,用我说的DMX解码的办法应该就可以识别的,就是判断第九位数据来判定是不是数据头.但如果你是要区分你这个信号和标准的DMX512信号,那还得想想办法...串行中断启动定时器不实际,中断太频繁...
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-24 18:37:32 | 显示全部楼层
spritels 发表于 2019-1-24 16:54
如果单纯是识别你要求的这个信号,用我说的DMX解码的办法应该就可以识别的,就是判断第九位数据来判定是不是 ...

是的,我尝试过在串口中加定时器,但是发现不行,所以现在卡着不知道怎么处理了,您要是有好的思路麻烦指点下小弟,不胜感激
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-25 10:36:32 | 显示全部楼层
简单给你介绍下我们做DMX解码的思路:串口正常配置成中断接收,接收到的数据,第九位是放在UART->CR1寄存器的最高位上的,根据DMX信号协议规则,第九位数据为0,则表明这个数据是整个DMX数据包的数据头,接下来的512个数据,第九位都是为1的.所以我们要做的事情就很简单了,只需要在中断服务里面判断一下CR1的最高位,如果为零就复位一下接收计数器就可以了.这是一种变通的DMX解码办法,对于标准或者是非标准的DMX信号都可以很好的识别的,我想对于你所说的这个信号应该也没有什么问题.
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-25 10:44:59 | 显示全部楼层
spritels 发表于 2019-1-25 10:36
简单给你介绍下我们做DMX解码的思路:串口正常配置成中断接收,接收到的数据,第九位是放在UART->CR1寄存器的 ...

好的,讲解的很详细,是一进中断就开启计数器计数,然后一直判断CR1最高为,为0的时候就停止计数,通过判断计数器计数的值来区分是不是标准的DMX信号对嘛? 判断完了之后在复位计数器,我理解的是这样吗?
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-25 11:04:56 | 显示全部楼层
NO,NO,计数器的作用是计数你所想取得的数据在整个数据包的位置,就像DMX的地址码.每次中断说明你已经接收到一位数据,然后判断CR1最高位是不是0,如果CR1最高位为0,则将计数器清零,接下来才能顺利取得第一个数据,第二个数据,第三个数据.........到下一个数据包头来到,它的CR1最高位又为0,然后又清零计数器,接着又是第一个数据,第二个数据,第三个数据.........如此反复...
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-25 11:14:30 | 显示全部楼层
至于来的是不是标准的DMX信号我们并不关心,只要数据包的格式符合DMX的标准就可以识别
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-25 11:24:43 | 显示全部楼层
spritels 发表于 2019-1-25 11:04
NO,NO,计数器的作用是计数你所想取得的数据在整个数据包的位置,就像DMX的地址码.每次中断说明你已经接收到 ...

哦,这个我明白,我也是通过这样可以正常接收DMX信号,现在我是在接受DMX信号的基础上,还要接收我图片上的这种信号,他与DMX信号的区别就在于break的时间长达2S,而标准的最长1S,我现在就是要接受这种非标准的信号,卡在这没进展,您这边有好的建议吗?
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-25 15:28:15 | 显示全部楼层
哇哦,很明显我的方法没有判断这个break的时间,所以只要是符合DMX数据格式的都可以接收,这就是所谓的非标准接收...
不要太纠结于break的长度,关键是起始数据的定位(第九位为0那一个),抓到它了,后面的数一个一个的自然就排好队了...
根据你要接收的数据的个数开一个缓冲,每次串行中断,判断第九位,第九位为0,计数器清零;第九位不为零,计数器加一,同时将数据按计数编号存入缓冲.很简单,就几个语句搞定...
主程序处理数据的时间间隔至少要大于一整个数据包的传输时间,考虑到信号刚接入时刻数据包的位置,大于两个数据包的传输时间比较安全.比如说DMX一个数据包时间大约是23ms,所以处理时间间隔要大于46ms,以保证所有数据都能缓冲正确...
好啦,都帮你帮到这份上了,就差帮你把程序写出来了.剩下的自己参透一下...改变一下思路,别老往一个方向上钻...
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-25 15:44:43 | 显示全部楼层
spritels 发表于 2019-1-25 15:28
哇哦,很明显我的方法没有判断这个break的时间,所以只要是符合DMX数据格式的都可以接收,这就是所谓的非标准 ...

谢谢大哥怎么详细的讲解,感激不敬,你让我对DMX信号有了更深的了解,我纠结那个break的时长,是因为当我2种不同信号过来时,我需要辨别出接收模式,当2S信号来了的话,我要将数据保存到eeprom中,如果是标准的数据,我只要接收显示就好了,所以我才这么纠结的
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-25 16:42:56 | 显示全部楼层
SOGA~原谅我一直没弄明白你的意思,原来你真的是要区分开两种信号...
鄙人的想法:设一个定时中断计数,比如每100ms加一,在串行接收中断接收到起始位的时候清0,如果遇到这个计数值到达20次以上(20次就是2S了)都没被清0,就是接收到你所说的这个信号了吧,正常DMX在2S内肯定是有起始位的.当然还要设一个再大一点的值,以便区分信号没有接入的情况...
回复 支持 反对

使用道具 举报

62

主题

902

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3555
金钱
3555
注册时间
2016-1-8
在线时间
543 小时
发表于 2019-1-25 17:02:03 | 显示全部楼层
请发求助帖,谢谢
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-25 18:04:02 | 显示全部楼层
spritels 发表于 2019-1-25 16:42
SOGA~原谅我一直没弄明白你的意思,原来你真的是要区分开两种信号...
鄙人的想法:设一个定时中断计数,比如 ...

正常情况应该是RX收到起始位才开始进入串口中断的,那没收到的话怎么进入串口中断开启定时器啊,我要在什么时候开启定时器呢?不太明白这里,之前我也是这样想的,但是不知道具体该在哪里开启,麻烦大哥指点下,谢谢
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-1-25 18:04:37 | 显示全部楼层

RE: 求路过的大哥指点下,卡在这点上一个多月了,一直调试有问题!

Sun_Fly 发表于 2019-1-25 17:02
请发求助帖,谢谢

对不起,新人不知道怎么发求助贴
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-1-26 09:02:11 | 显示全部楼层
胡松松 发表于 2019-1-25 18:04
正常情况应该是RX收到起始位才开始进入串口中断的,那没收到的话怎么进入串口中断开启定时器啊,我要在什 ...

定时器不在串口中断开,而是程序运行就要打开...
我的意思是设一个计数值,比如定时器每100ms中断一次就让它加1,当串口没有中断过来的时候,这个值就会一直往上加,加到一定的数值你就可以判断为无信号输入的状态(当然它快溢出的时候你也要及时处理).当有串口中断过来,你判断到起始数据(第九位为0那个),你就将这个计数值清零.DMX信号的两个起始数据之间间隔是很短的,就算去到1S,那你这个计数值最多也就是计到10就会被清零.接收你说的这个信号也同理,2S的间隔最多也就计到20吧,这样判断这个计数值就可以知道来的信号是DMX还是你说的这个了...
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-13 14:35:59 | 显示全部楼层
spritels 发表于 2019-1-26 09:02
定时器不在串口中断开,而是程序运行就要打开...
我的意思是设一个计数值,比如定时器每100ms中断一次就让 ...

大哥新年好,您说的这个是可以做到的,但是有个问题,就是程序在频繁进入定时器中断中,假如我串口中断接受数据完成后,他会退出中断,但是我还要根据串口接受到的数据进行相关运算和其他操作,这样频繁进入中断会不会有影响呢?
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-11-14
在线时间
15 小时
发表于 2019-2-13 18:07:37 | 显示全部楼层
我随便说一下,RX信号一路进RX,再同时进入另外一个普通IO,用10MS中断去检测这个2S低电平,不知道这样可以不可以。
回复 支持 反对

使用道具 举报

3

主题

1906

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4100
金钱
4100
注册时间
2018-8-14
在线时间
695 小时
发表于 2019-2-13 19:44:11 | 显示全部楼层
很多协议都有这个Command, 它不是什么复位码, 而是用作唤醒睡眠中的CPU, usart的Rx端一般是不需要配置为AF, 而是Input_floting, 就是让你可以同时以这IO作为唤醒, 或中断的使用,按这思路想吧
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-14 09:33:20 | 显示全部楼层
edmund1234 发表于 2019-2-13 19:44
很多协议都有这个Command, 它不是什么复位码, 而是用作唤醒睡眠中的CPU, usart的Rx端一般是不需要配置为 ...

还是不太明白,您的意思是先将串口配置成普通IO,进行识别后再将串口打开?通过这样去识别吗?
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-14 09:34:10 | 显示全部楼层
lqd_sam_wong 发表于 2019-2-13 18:07
我随便说一下,RX信号一路进RX,再同时进入另外一个普通IO,用10MS中断去检测这个2S低电平,不知道这样可以 ...

硬件已经固定好了,不允许这样做
回复 支持 反对

使用道具 举报

3

主题

1906

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4100
金钱
4100
注册时间
2018-8-14
在线时间
695 小时
发表于 2019-2-14 10:34:03 | 显示全部楼层
胡松松 发表于 2019-2-14 09:33
还是不太明白,您的意思是先将串口配置成普通IO,进行识别后再将串口打开?通过这样去识别吗?

不需要, usart的rx端本来就是配置为输入的, 即它同时是usart_rx, 也同时可以读的IO, 可以用作中断
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-14 11:36:38 | 显示全部楼层
edmund1234 发表于 2019-2-14 10:34
不需要, usart的rx端本来就是配置为输入的, 即它同时是usart_rx, 也同时可以读的IO, 可以用作中断

能简单说下我需要怎么写代码吗?  现在思路还是不明白,谢谢大哥
回复 支持 反对

使用道具 举报

3

主题

1906

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4100
金钱
4100
注册时间
2018-8-14
在线时间
695 小时
发表于 2019-2-14 11:49:09 | 显示全部楼层
胡松松 发表于 2019-2-14 11:36
能简单说下我需要怎么写代码吗?  现在思路还是不明白,谢谢大哥

你可以把rx的io配置为外部中断边缘触发, 在需要等待reset时使能它, 收到来reset command后关掉此外部中断
下降沿后计时1.5秒, 上升沿就复位计时器,计时器益出就是收到复位的command了
回复 支持 反对

使用道具 举报

2

主题

41

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
419
金钱
419
注册时间
2014-7-30
在线时间
263 小时
发表于 2019-2-14 14:44:02 | 显示全部楼层
。。。真佩服你。
复位信号是由 同步头(复位码)+0起始段+数据
串口协议是UART。两种时序是这样子。STM8S003的UART有帧错误中断,如果停止位没有在预期的时间上接收和识别出来,就会发生中断。
从两张图片可以看出来,UART的起止位是低电平,停止位是高电平,然后复位信号的复位码是>2S的低电平,这个复位信号会使UART进入中断,进入中断(判断为帧错误中断,那样就可以区别两种不同信号了)后,将串口输入口禁止UART功能,做为普通输入IO口,然后打开定时器解析这个复位信号,或者可以用一路IO输入捕获与RX硬件相连解析这个复位信号

UART时序

UART时序

复位信号时序

复位信号时序
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-14 15:23:51 | 显示全部楼层
503126063 发表于 2019-2-14 14:44
。。。真佩服你。
复位信号是由 同步头(复位码)+0起始段+数据
串口协议是UART。两种时序是这样子。STM8 ...

谢谢大哥,我试过用错误帧检测的,但是当我要识别1S低电平和2S低电平复位信号的时候,两者应该都会导致帧错误的,所以应该区分不出来吧?
回复 支持 反对

使用道具 举报

2

主题

41

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
419
金钱
419
注册时间
2014-7-30
在线时间
263 小时
发表于 2019-2-14 15:26:09 | 显示全部楼层
胡松松 发表于 2019-2-14 15:23
谢谢大哥,我试过用错误帧检测的,但是当我要识别1S低电平和2S低电平复位信号的时候,两者应该都会导致帧 ...

检测到复位信号,你还测不出1S和2S区别吗?打开定时器检测
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-14 15:27:30 | 显示全部楼层
edmund1234 发表于 2019-2-14 11:49
你可以把rx的io配置为外部中断边缘触发, 在需要等待reset时使能它, 收到来reset command后关掉此外部中 ...

好的,谢谢
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-14 15:33:02 | 显示全部楼层
503126063 发表于 2019-2-14 15:26
检测到复位信号,你还测不出1S和2S区别吗?打开定时器检测

能麻烦说的详细点吗?我代码思路改怎么写, 小弟愚昧,初学单片机,见笑了,谢谢!
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-2-18 11:08:58 | 显示全部楼层
本帖最后由 spritels 于 2019-2-18 11:34 编辑
胡松松 发表于 2019-2-13 14:35
大哥新年好,您说的这个是可以做到的,但是有个问题,就是程序在频繁进入定时器中断中,假如我串口中断接 ...

今天才上班...
定时器的100ms中断时间,要远远大于你这个信号的数据帧的时间.标准DMX信号一帧数据是44us,所以串口中断每44us就会发生一次,然后是中断处理:判断第九位,计数器操作,缓存数据,这个过程都是us的级别....如果你在下一个数据到来之前(期间至少有44us时间)都不能接收完上一个数据,那要么你的程序有问题,要么你得换一个更快的单片机了...
中断服务程序要尽量的短,仅仅是缓存数据就可以了,数据处理这种复杂的任务放在外面执行...
当然你所说的,定时中断和串口中断同时发生的情况,会有,但只要你的中断服务程序足够短(比如说进去一两个语句就出来了),OK,没问题,根本没有影响,它会根据自己的优先级处理机制处理...
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-2-18 11:31:33 | 显示全部楼层
当然,为了提高系统的可靠性,必要的出错处理机制还是要有的,比如说连续接收到两个一样的数据才采用,否则丢弃...
鄙人是做灯光的,走的都是DMX协议,我用的是S105这个系列的,处理这个卓卓有余了...我们还要处理按键,数码管扫描,还有别的外设...
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-18 13:16:13 | 显示全部楼层
spritels 发表于 2019-2-18 11:31
当然,为了提高系统的可靠性,必要的出错处理机制还是要有的,比如说连续接收到两个一样的数据才采用,否则丢弃 ...

谢谢大哥的耐心讲解,代码我已经写好了,但是今天硬件在线调试的时候发现还是不行,当2S的信号发过来的时候,串口的2种状态都进去了,您可以的话帮我看下是不是哪里语句有问题,谢谢!
[mw_shl_code=c,true]#include "iostm8s003f3.h"
#include "Tim1.h"
unsigned char pwm[3];//={0,0,0};//接收数据缓存区
unsigned char check[8];
FlagStatus  DMX_display;
FlagStatus  check_flag ;
static unsigned int address_counter;      //串口接收数据长度
extern unsigned char counter;
/*************************************  
* 函数名称:Init_UART1  
* 函数功能:UART1 初始化
* 入口参数:无  
* 出口参数:无  
****************************************/
void Init_UART1(void)
{     
// CLK_PCKENR1 |= 0X04;  //使能USART1时钟
  
  UART1_CR1=0x10; //9位数据+1stop
  UART1_CR2=0x00;
  UART1_CR3=0x00;//1 stop
  // 必须先写BRR2
  // 例如对于波特率位250000时,分频系数=16000000/250000=64
  // 对应的十六进制数为0040,BBR1=04,BBR2=00
  
  UART1_BRR2=0x00;
  UART1_BRR1=0x04;
  
  UART1_CR2=0x2c;//允许接收,发送,开接收中断
}


/*************************************  
* 函数名称:UART1_RX_RXNE
* 函数功能:UART1 接收中断函数
* 入口参数:无  
* 出口参数:无  
****************************************/

#pragma vector=UART1_R_RXNE_vector
__interrupt void UART1_RX_RXNE(void)
{  
  unsigned char RxBuf=0;        //临时接收
  unsigned char temp;      
  static unsigned char RxData[513]; //临时接收数据缓存区   
  static unsigned char Rx_addressData[20]; //临时接收数据缓存区                                                                       
  static unsigned char start_code=0;    //判断start_code
  static unsigned char  break1=0;  //判断break
  //FlagStatus  address_flag=0;    //判断address 模式下复位码
  static unsigned char address_start_code=0;    //判断start_code
  static unsigned char address_temp=0;    //判断start_code
   if(UART1_SR_RXNE==1)
  {
       UART1_SR_RXNE=0;   //清RXNE
      if (UART1_SR_OR_LHE)
        {
        // 发生过载错误,顺序读UART1_SR, UART1_DR来清UART1_SR_OR_LHE位
              RxBuf = UART1_SR;
              RxBuf = UART1_DR;    // 做一些错误处理 清OR   
        }
     else
    {                                    
       RxBuf = UART1_DR;
      if(UART1_CR1_R8==0)   //判断第九位
       {
             TIM2_CR1 |= 0x80;//  关定时器
             temp = counter;  //读定时器计数的值;
             counter=0 ;//清0
             if(temp<10)     break1=1;  //显示模式-复位码小于1S
             else if((temp>10)&&(temp<21))  break1=2;  //复位码大于1S小于2S模式
               //break1=1;
        }
      if (break1==1)    //显示模式-复位码小于1S
        {
          start_code=0;
          address_counter=0;
          DMX_display=0;
         }
          if((address_counter==0)&&( RxBuf==0))
            {
              start_code=1;            
            }
            
          if (start_code==1)
            {
              RxData[address_counter] =RxBuf;
              address_counter++ ;
              if(address_counter>512)
              {
                break1=0; start_code=0; address_counter=0;
                DMX_display=1;
                pwm[0]= RxData[2];
                pwm[1]= RxData[3];
                pwm[2]= RxData[4];
              }
            }
         //}
      if(break1==2)  //复位码大于1S小于2S
         {
           address_start_code=0;
           address_temp=0;
           check_flag=0;  
          }
           if((address_temp==0)&&( RxBuf==0))
             {
                address_start_code=1;    //收到start_code
                DMX_display=0;  //黑屏           
             }
           if((address_start_code==1)&&(PB_IDR_IDR5==1))
             {
                Rx_addressData[address_temp] =RxBuf;
                address_temp++ ;
                if(address_temp>10)
                {
                  break1=0; address_start_code=0; address_temp=0;
                  check_flag=1;
                  check[0]= Rx_addressData[2];
                  check[1]= Rx_addressData[3];
                  check[2]= Rx_addressData[4];
                  check[3]= Rx_addressData[5];
                  check[4]= Rx_addressData[6];
                  check[5]= Rx_addressData[7];            
                  check[6]= Rx_addressData[8];
                  check[7]= Rx_addressData[9];
                }
             }
          }
     }
   //}
}[/mw_shl_code]
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-18 13:19:49 | 显示全部楼层
胡松松 发表于 2019-2-18 13:16
谢谢大哥的耐心讲解,代码我已经写好了,但是今天硬件在线调试的时候发现还是不行,当2S的信号发过来的时 ...

下面的是定时器2的初始化和中断函数,单片机一上电就初始化定时器并打开开始计数
[mw_shl_code=c,true]#include "iostm8s003f3.h"
#include "Tim1.h"

unsigned char counter =0;

/********************************************************************************************************
*  Function: TIM2_Init                                                                        
*  Object: TIM2初始化
*  输入: 无
*  输出: 无                                         
*  备注:  无
********************************************************************************************************/

void TIM2_Init(void)
{
  disableInterrupt;   //禁止总中断
  TIM2_IER  = 0x00;  //禁止中断

  TIM2_EGR  =0x01;   //允许产生更新标志
  TIM2_PSCR =0x07;   //设置时钟分频 16M/128=0.125MHz---8us
  TIM2_ARRH = 0x30;  //0x30D4=12500;  周期=12500次,每8*12500=100Ms复位一次定时器2
  TIM2_ARRL = 0xD4;  //ARR自动装载值,每8us递减1         

  TIM2_CNTRH=0x00;   //初值
  TIM2_CNTRL=0x00;

  TIM2_CR1 |= 0x81;  //开启定时器0X81
  TIM2_IER |= 0x01;  //允许中断
  EnableInterrupt;   //使能中断

}

#pragma vector = TIM2_OVR_UIF_vector
__interrupt void TIM2_OVER_UIF(void)
{
  TIM2_SR1_UIF = 0;//清除中断标志位
  ++counter;
  if(counter>254){counter=21;}  //接近溢出的话就直接从21开始++
}
[/mw_shl_code]
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-2-18 13:41:04 | 显示全部楼层
大GUO~你的串口中断服务一看就太长了啦...像那些什么判断复位码长度,显示模式什么的,完全应该放在外面来做啦...
而且,你串口中断一次,其实只收到了一个数据而已,你的check[0]~check[7]一共八个数据,你往哪里取....
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-2-18 16:40:28 | 显示全部楼层
给个DMX512的代码你参考参考
[mw_shl_code=cpp,true]//===================================================================================================
//串行中断服务程序
//===================================================================================================
@far @interrupt void UART2_RxOver_Interrupt(void)
{
                //读数据,清中断标志
                temp3 = UART2_SR;
                temp2 = UART2_DR;
                temp1 = UART2_CR1;
               
                if(!(temp1&0x80))    //如果第9位数据为0,表示这是数据头
                        {
                                dmx_count=0;
                                receive_count=0;
                                receive_flag=0;
                                receive_time=0;   //此值在定时中断中自加,用来判断有没有信号以及break长度
                        }       
                else
                        {
                                if(receive_flag==1)
                                        {
                                        if(receive_count<8)   //接收8个通道
                                                {
                                                  dmx_data[receive_count]=temp2;   //缓存数据
                                                  receive_count++;
                                                }       
                                        }
                                else
                                        {
                                                if(dmx_count==address)             //确定接收起始地址
                                                        {
                            receive_flag=1;
                                                          dmx_data[receive_count]=temp2;  //缓存数据
                                                          receive_count++;
                                                        }
                                                dmx_count++;
                                        }
                        }
}[/mw_shl_code]
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-19 13:17:13 | 显示全部楼层
spritels 发表于 2019-2-18 16:40
给个DMX512的代码你参考参考
[mw_shl_code=cpp,true]//================================================ ...

谢谢大哥,按到你的意思,我想了下,主要有3点问题,第一:这个receive_time=0;   //此值在定时中断中自加,用来判断有没有信号以及break长度, 我在外面判断需要在定时器中断函数中判断吗?还是直接就是写个判断函数通过receive_time的值来选择模式;第二:全程都不需要关定时器吗?  第三:如果多个这样的芯片,同时接收数据的话,只截取DMX512上面的几个数据,只是地址不一样,我要显示的时候会不会存在显示不同步啊?理论上不是应该截取完一怔数据在同时显示的吗?
回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-2-19 15:40:13 | 显示全部楼层
胡松松 发表于 2019-2-19 13:17
谢谢大哥,按到你的意思,我想了下,主要有3点问题,第一:这个receive_time=0;   //此值在定时中断中自 ...

回一:不是说另外开一个100ms的定时么,在定时中断里面给个标志,在主函数里面判断就好了,同样这个标志也可以用来处理数据...切记快速退出中断...
回二:定时器就一直开着就好,没必要关掉...
回三:不知道你这信号一整包数据有多长,像DMX512的话,一整包才20多ms,就算你100ms处理一次数据并显示,那显示的数据最多也就差100ms吧,你确定你能看出来差别么...
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-20 10:15:55 | 显示全部楼层
spritels 发表于 2019-2-19 15:40
回一:不是说另外开一个100ms的定时么,在定时中断里面给个标志,在主函数里面判断就好了,同样这个标志也可 ...

好的,谢谢大哥,我重新改下代码试试
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-23 15:44:33 | 显示全部楼层
spritels 发表于 2019-2-19 15:40
回一:不是说另外开一个100ms的定时么,在定时中断里面给个标志,在主函数里面判断就好了,同样这个标志也可 ...

大哥,今天按到您给的提升,重新搞了下代码,串口中断时按到您给的那个参考写的,但是在判断receive_time这里还是有问题,麻烦帮我看下,在无信号的时候 DMX_address=1 也执行
! [mw_shl_code=c,true]#include "clk_conf.h"
#include "Tim1.h"
#include "GPIO.h"
#include "Delay.h"


extern unsigned char dmx_data[8]; //接收数据缓存区
extern const unsigned short gama[256];
extern unsigned char receive_time;

FlagStatus   DMX_display ;
FlagStatus   DMX_address ;


int main( void )
{
  unsigned char R_temp,G_temp,B_temp;  
  Clk_conf();
  Tim1_PWM_conf(65535,TIM1_DIV1); //16M   f=16/65535
  TIM2_Init();
  Init_UART1();
  Delay_MS();
  EnableInterrupt;
while(1)
  {

    if(receive_time>30)       {DMX_display=0; receive_time=0 ;}   //3S无信号黑屏
    else if(receive_time<10)  {  DMX_display=1 ;}               //小于1S,显示模式
    else if((receive_time<25)&&(receive_time>10)&&(PB_IDR_IDR5==1)) { DMX_address=1;}

    if(DMX_display==1)
    {
      R_temp = dmx_data[0];
      G_temp = dmx_data[1];
      B_temp = dmx_data[2];
      To_PWM_output(gama[R_temp],gama[G_temp],gama[B_temp]);
      DMX_display=0 ;
    }
   //else {To_PWM_output(0,0,255);}//无信号
  }

}[/mw_shl_code]



#include "iostm8s003f3.h"
#include "Tim1.h"

unsigned char receive_time;


/********************************************************************************************************
*  Function: TIM2_Init                                                                        
*  Object: TIM2初始化
*  输入: 无
*  输出: 无                                         
*  备注:  无
********************************************************************************************************/

void TIM2_Init(void)
{
  disableInterrupt;   //禁止总中断
  TIM2_IER  = 0x00;  //禁止中断

  TIM2_EGR  =0x01;   //允许产生更新标志
  TIM2_PSCR =0x07;   //设置时钟分频 16M/128=0.125MHz---8us
  TIM2_ARRH = 0x30;  //0x30D4=12500;  周期=12500次,每8*12500=100Ms复位一次定时器2
  TIM2_ARRL = 0xD4;  //ARR自动装载值,每8us递减1         

  TIM2_CNTRH=0x00;   //初值
  TIM2_CNTRL=0x00;

  TIM2_CR1 |= 0x81;  //开启定时器0X81
  TIM2_IER |= 0x01;  //允许中断
  EnableInterrupt;   //使能中断

}

#pragma vector = TIM2_OVR_UIF_vector
__interrupt void TIM2_OVER_UIF(void)
{
  TIM2_SR1_UIF = 0;//清除中断标志位
   ++ receive_time;

}




回复 支持 反对

使用道具 举报

0

主题

78

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1588
金钱
1588
注册时间
2018-10-11
在线时间
224 小时
发表于 2019-2-25 09:14:19 | 显示全部楼层
if(receive_time>30)       {DMX_display=0; receive_time=0 ;}   //3S无信号黑屏

这里,每次这个值大于30你就把他清零了,自然也就从0加起,接着再执行到下面两句:

else if(receive_time<10)  {  DMX_display=1 ;}               //小于1S,显示模式
    else if((receive_time<25)&&(receive_time>10)&&(PB_IDR_IDR5==1)) { DMX_address=1;}

所以会执行到DMX_address=1这里...

改成:

if(receive_time>30)       {DMX_display=0; receive_time=30 ;}   //3S无信号黑屏

试试....
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
179
金钱
179
注册时间
2019-1-3
在线时间
30 小时
 楼主| 发表于 2019-2-28 13:34:52 | 显示全部楼层
胡松松 发表于 2019-1-5 13:28
不太明白,是在串口接收中断中启动定时器吗?麻烦解惑下,感谢

[mw_shl_code=c,true]收藏
评论(0)
分享到
微博
QQ
微信
LinkedIn
void Time0_Init() { TMOD=0x01; IE=0x82; TH0=0xff; TL0=0xbd; TR0=1; } void Time0_Int() interrupt 1 { switch(bs) { case 0: if(count_x==0) { TL0=187; TH0=251; P1=pout[djsx[0][count_b*6]]; count++; break; } if(count_x!=3) { TL0=ys[0][count_x-1][0]; TH0=ys[0][count_x-1][1]; P1=pout[djsx[0][count_b*6+count_x]]; bs=1; break; } P1=pout[djsx[0][count_b*6+3]]; case 1: TL0=ys[1][count_x-1][0]; TH0=ys[1][count_x-1][1]; P1=P1+pout[djsx[1][count_b*6+count_x]]; bs=0; count++; } if(bs==0) { if(count==xzsd) { count=0; count_x=count_x+xzbs; } if(count_x==6) { count_x=0; count_b++; } if(count_x==-1) { count_x=5; count_b--; } if(count_b==4)count_b=0; if(count_b==-1)count_b=3; } } void main() { P1=0; Time0_Init(); while(1); }[/mw_shl_code]
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 14:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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