完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
`` 简 介: 宋雪松老师,论坛用户名@Kinst。著有《手把手教你学51单片机(C语言版)》。擅长扩频通信、OFDM通信技术、测量仪器相关技术,曾从事过5年的通信算法研究,现在创业中,他的团队开发除了具有独立知识产权的LA5016,LA2016逻辑分析仪。酷爱技术,喜欢追求卓越。
你有问题吗???
活动获奖规则: 为了鼓励踊跃提问,宋雪松老师会在问答结束后从提问者中选取 2 名幸运会员赠予《手把手教你学51单片机(C语言版)》一书。 Elecfans高手问答一贯的风格,不欢迎任何与主题无关的讨论和喷子。 社区高手招募 ************************************************************************** Elecfans高手问答往期回顾:`` 本帖被以下淘专辑推荐:
|
|
相关推荐
36个回答
|
|
|
|
|
|
写了一段AT89C52的C51程序进行MODBUS-RTU数据传输,我是利用KEIL V3.3,MODSCAN32,虚拟串口VSPD这三个软件在电脑上进行程序模拟的。
传输采用2400波特率,MODSCAN32发送数据,KEIL接收,由于MODBUS数据帧与帧之间必须大于3.5个字符的间隔时间,所以程序中采用了2ms定时器中断,定时中断程序中有计数变量n,程序中开了串口中断(中断优先级高于定时器中断),当单片机有接收中断(即RI=1),n就清0,否则当n大于10时(相当于20ms,大概4个字符的间隔时间),判断为有新数据帧传输,标志寄存器_time4为超时标志,为1时表示超时。 可是在调试时,发现KEIL接收数据时,计数变量要远大于10时,才能保证数据被正确接收,这里采用了一个数据组receivedata[k]来接收MODSCAN32传输过来的数据,否则,传输过来的数据没法完全接收,数据中字节与字节之间时间间隔大于计数变量10的,数据就被程序忽略了,我程序中n的值都设到300了,但还是偶然会发生上述传输超时的问题?下面是程序中的字节接收和接收中断程序。 void recebyte(void)//字节接收 { if(标志寄存器_time4==1) { temp[0]=SBUF; RI=0; 标志寄存器_time4=0; n=0; if(temp[0]==fzdz)//如果接收数据等于分站地址 { receivedata[0]=temp[0]; 标志寄存器_dztg=1;//地址验证通过标志置1 k=1;//k置1,表示接收了第一个字节数据 } } else if(标志寄存器_time4==0)//不超时,表示有数据传输 { if(标志寄存器_dztg==1)//如果地址通过,则继续接收数据 { temp[0]=SBUF; RI=0; receivedata[k]=temp[0]; k++;//接收字节计数器加1 } else RI=0; n=0;//总线上有数据传输,2ms计数清零 } } void comRi(void) interrupt 4 { if(RI) recebyte();//接收一个字节数据 } 本人觉得2400的波特率,开了串口中断,数据接收时不应该出现超时的现象才对啊,真弄不清哪里出了问题?@kinst 请教了 |
|
|
|
我用1602显示1302的时钟 ,用键盘扫描调时间,不按按键的时候,时间显示 并正常变化,而当按按键的时候 本应该是按一下 小时加或减一的 可显示的是胡乱变化,小时设置的是==24;则清零,可有时候会超过24;
键盘扫描 以及返回值没问题,因为程序是我模仿别人的改的,他写的程序我试过 完全正常显示,,可我把他的部分程序搬过来后就不正常了,,想请教一下宋老师@kinst 到底是怎么个情况呢? |
|
|
|
来看看,刚学习单片机开发,不过还是来学习学习~
|
|
|
|
|
|
|
|
|
|
|
|
程序问题自己调试吧,用示波器测测波形找问题,程序问题不是用眼睛看的。 |
|
|
|
用更高晶振,速度更快的单片机,会调0.08就会0.02,没有区别 |
|
|
|
unsigned char SD_spi_read() //SPI读一个字节 { SD_SO=1; SD_SCL=1; if(is_init) delay(DELAY_TIME); SD_SCL=0; if(is_init) delay(DELAY_TIME); _dat7=SD_SO; SD_SCL=1; if(is_init) delay(DELAY_TIME); SD_SCL=0; if(is_init) delay(DELAY_TIME); _dat6=SD_SO; .....} 按照他的程序看,是在下降沿后读取的,但是通常我们不是在下一个上升沿(数据稳定)才读取的吗?@kinst |
|
|
|
[size=14.4444446563721px]首先看一个CRC8的校验程序,是DS18B20使用的G(x)=x^8+x^5+x^4+1;[size=14.4444446563721px]uint8_t CRC8( uint8_t *P,uint8_t Len )
{ uint8_t num,Data; uint8_t CRC_Reg=0; while(Len--) { Data = *P; for (num=0;num<8;num++) { if ((Data^CRC_Reg)&0X01 != 0) // DS18B20数据的最低位开始移入移位寄存器 { // 若数据的最低位与移位寄存器的最低位异或结果为1 //CRC_Reg ^= 0X18; // 第四五位与1做或运算并且存入移位寄存器 //CRC_Reg >>= 1; // 移位寄存器数据右移一位 //CRC_Reg |= 0X80; // 运算结果1存入数据移位寄存器最后一位 CRC_Reg >>= 1; CRC_Reg ^= 0X8C; } else { // 若数据的最低位与移位寄存器的最低位异或结果为0 // 第四五位与0做异或运算并且存入移位寄存器,0做异或运算为原数值 CRC_Reg >>= 1; // 移位寄存器数据右移一位,与此同时也完成了末位添加0的运算 } Data >>= 1; } P++; } return CRC_Reg; } 上一个测试了一下没什么问题,又编写了CRC16CCIT的G(x)=x^16+x^12+x^5+1;uint16_t CRC_CCIT_16( uint8_t *P,uint16_t Len ) //指针指向的数据顺序影响校验结果, { //此计算过程先计算指针指向的最低字节 uint16_t CRC_Reg; uint8_t num; uint8_t Data; CRC_Reg = 0; while(Len--) //剩余需要校验的字节数 { Data = *P; for (num=0;num<8;num++) //每一个校验字节要移动8次 { if ((Data^CRC_Reg)&0X0001 != 0) //校验数据从LSB开始 { CRC_Reg >>= 1; //判断完成后将最低位移除 CRC_Reg = CRC_Reg^0X8408; /*CRC_Reg |= 0X8000;*/ //0X8408可将最高位设置为1 } else { CRC_Reg >>= 1; } Data >>= 1; } P++; } return CRC_Reg; } 但是这个程序就有问题,我一直没照找到哪里有问题!下面给一个网络上找的自己稍微修改了一下,没什么问题,uint16_t CRC16( uint8_t *P,uint16_t Len ) { uint16_t CRC=0; uint8_t Data,i; while(Len--) { Data = *P; for(i=0x01;i!=0;i<<=1) { if ((CRC&0X8000)!=0) { CRC <<= 1; CRC ^= 0X1021; } else { CRC <<= 1; } if((Data&i)!=0) CRC ^= 0X1021; } P++; } return CRC; } 问题来了,我的第二个程序自己是将第三个正确程序的CRC_Reg(移位寄存器)左右颠倒使用,再就是将数据移入位和从寄存器移出的那一位的异或结果一次性判断来完成。不知道表述清楚没,希望有心的人给看看不胜感激!就当自己复习了,我比较愚钝看了三天还是无解······ @kinst |
|
|
|
如何用一句话描述电机控制、PLC和单片机的关系呢 @@kinst 宋老师可以说说不
|
|
|
|
目前我在做一个通过SPI总线读取EEPROM的程序,使用的是STC15单片机,标准的SPI接口 非软件模拟。
但是由于需要读取的EEPROM是在别的PCB上已经焊接好的,所以 我通过一个SOP8的测试夹来进行连接。在软件调试中遇到了很多问题。 1. 如果我使用一个按键来触发读取操作,则单片机在连接PCB上电后,读取的内容一直为0,后来经过研究我发现PCB上的EEPROM的电源与PCB其他芯片的电源共通的,也就是说 存在其他芯片干扰数据读取。(后来通过示波器发现,需要读取的PCB板上的ARM芯片会在上电300ms以后将EEPROM的MISO拉低 内部估计是开漏状态,用万用表测量下是直接接地了)。 2. 基于第一点,我为了验证,就在程序里设置为上电初始化的时候执行一次读取(上电300ms以内),此时的数据就对了。 但是设计功能时候就要求必须用一个按键触发读取指令,我也想过讨巧的办法,就是在上电后读取一次,把数据暂存起来,按键触发时候直接就把数据显示出来就行了。但是因为还有其他功能,所以在初始化时候执行读取,会影响其他功能。 3. 然后我就想到,用三极管做为开关,在按键触发后,导通EEPROM的电源,然后读取完毕 就关断。使用的NPN管子(手头上有现成的) E极直接接地,+5V和C之间接需要读取的芯片,同时为了验证 我还并了一个发光二极管(包含限流电阻)来做为状态指示。然后通过单片机引脚来驱动三极管 (单片机口有上拉10K电阻)。在没有连接芯片时候,通过LED状态能够看到三极管能够可靠打开与关断,但是连接了EEPROM后,上电初始化没问题,三极管打开一次,之后当单片机输出为0时候,LED依然有微弱的亮光,可以判定三极管并没有可靠关断。 求原因,我下一步准备在单片机输出口和三极管B极加一个二极管。 |
|
|
|
通过串口助手(9600-8-0-1)发送三个字节,如果首字节为0x34,则返回两个字节0x03、0x00,继续等待接受新输入;如果首字节不是0x34,则不作应答,等待接受新输入。调试发现如果连续手动输入34 01 02返回结果正确,可一旦输入首字节不是34(如01 02 03),则再输入34 01 02也没有反应了。通过观察窗发现最后输的34 01 02没有被读进数组receive。然后加入else那一段,即首字节不是34的话就返回ff,这样两种情况都正常返回,且可以连续输入。看上去好像要再接受字符的话必须要先发送字符?没道理啊,请@kinst 帮帮忙。
我用的是C8051F310。本来是在编modbus从机端程序如果从机号不对的话就不响应,结果也是不能接受新的命令帧了。。 #include "initial.h" #include typedef unsigned char byte; byte send[20]; //用于存放发送的数据,最大ModBus帧是256字节 byte receive[20]; //用于存放接收的数据 byte rec_ptr; //用于给接收到的数据编号 byte rec_flag; //rec_flag=1时表示已接收到一帧数据,对数据帧解析完rec_flag被置为0 byte rec_bytes; //接收的字节数 main(void) { byte i; byte *ssd; rec_ptr = 0; rec_flag= 0; PCA0MD &= ~0x40; // WDTE = 0 关闭看门狗,上电默认打开 Init(); EA=1; //允许所有中断 while(1) { while (rec_flag==1) { send[0]= rec_bytes; send[1]= 0x00; ssd = send; if(receive[0] == 0x34) { for(i=0;i<2;++i) { ACC = *ssd; TB80 = ~P; SBUF0=*ssd++; while(TI0==0); TI0=0; } } /* else { ACC = *xFF; TB80 = ~P; SBUF0=0xFF; while(TI0==0); TI0=0; } */ rec_flag=0; } } } void uart0(void) interrupt 4 { if(RI0) { RI0=0; receive[rec_ptr++] = SBUF0; // rec_ptr初始值为0,每接受一个数据便自增1 if (rec_ptr==3 ) { rec_bytes = rec_ptr; rec_ptr = 0; rec_flag = 1; } } } 复制代码 |
|
|
|
谢谢分享@@@!!!!!!
|
|
|
|
这个看门狗着实让人茅塞顿开啊。原来如此 |
|
|
|
如果你有好的想法、好的创意,那就不要让它在脑海中发霉,只有比别人更早,更快的努力,才能尝到成功的滋味
|
|
|
|
看门狗的描述真好
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
157 浏览 0 评论
【每周推荐】采用11代Intel CPU,基于youyeetoo X1开发板搭建少儿AI智能STEAM积木平台
825 浏览 0 评论
2372 浏览 2 评论
【youyeetoo X1 windows 开发板体验】+ 影音处理和AI模型移植
2226 浏览 5 评论
I.MX6ULL-飞凌 ElfBoard ELF1板卡- 移植zbar的方法
1694 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
5713 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-23 16:04 , Processed in 0.732939 second(s), Total 84, Slave 67 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号