搜索

tag 标签: 通信

相关帖子

版块 作者 回复/查看 最后发表
工业级4G路由器需要满足哪些要求 工控电子 蓝先生 2020-5-21 2 72 蓝先生 5 天前
通信网络中的透传到底什么意思? 工控电子 蓝先生 2020-5-11 1 188 aytwartoofyoroo 2020-5-11 10:50
振动方向与波的传播方向是不是像虎门大桥的律动 attach_img RF/无线 btty038 2020-5-10 0 303 btty038 2020-5-10 20:36
通信网络中的透传到底什么意思? RF/无线 蓝先生 2020-4-26 4 889 chunyang 2020-4-26 17:32
RS-485 的电力线通信仿真参考设计 attach_img 【模拟与混合信号】 Jacktang 2020-4-24 3 401 okhxyyo 2020-4-26 17:01
用网络损伤仿真验证网络系统的可靠性 attach_img 信息发布 wenzhankwji 2020-4-13 0 0 wenzhankwji 2020-4-13 20:58
USB协议的DSP高速上位机接口设计 【DSP 与 ARM 处理器】 Jacktang 2017-6-27 0 808 Jacktang 2017-6-27 22:27
TI 28035 如何利用ECAN设计可靠通信? 【微控制器 MCU】 huzi741 2017-6-26 2 2073 huzi741 2017-7-5 16:04
关于软件I2C与MSP430通信的问题 【DSP 与 ARM 处理器】 灞波儿奔 2017-6-21 0 303 灞波儿奔 2017-6-21 21:05
请问办理电子通信广电行业行业电子工程行业乙级资质办理要多少人员配置和业绩 attach_img 信息发布 一米之上 2017-6-19 0 909 一米之上 2017-6-19 20:00
提供与招聘初始一级机电一级通信广电建造师挂资质 要求考B数名 信息发布 zsgk2016 2017-6-11 0 505 zsgk2016 2017-6-11 23:54
本单位现缺中高级通信相关专业工程师兼职 信息发布 扣1780051410 2017-6-12 0 404 扣1780051410 2017-6-12 17:38
现在高级通信是不是太多啦没有单位要? 信息发布 13138685585 2017-6-13 0 505 13138685585 2017-6-13 18:20
本单位现缺中高级通信相关专业工程师兼职 信息发布 扣1780051410 2017-6-14 0 505 扣1780051410 2017-6-14 17:12
本单位现缺中高级通信相关专业工程师兼职,费用高,全国不限 信息发布 扣1780051410 2017-6-15 0 505 扣1780051410 2017-6-15 16:40
本单位现缺中高级通信相关专业工程师兼职 信息发布 扣1780051410 2017-6-20 0 505 扣1780051410 2017-6-20 18:43
我的高级通信工程师找单位啊,,, 信息发布 13138685585 2017-6-20 2 771 13138685585 2019-3-3 15:18
基于msp430g2553无线通信cc1101收发程序详解 attachment 【微控制器 MCU】 Jacktang 2017-6-26 0 723 Jacktang 2017-6-26 21:04
通信故障 attach_img 单片机 cgu 2020-3-3 3 1362 cgu 2020-3-4 14:27
拓普微智能模块通信接口如何连接(一) attach_img 工控电子 慈俭不敢为人先 2020-3-25 1 233 兰博 2020-3-26 09:50

相关日志

分享 推荐2本学习Modbus通信协议的资料书
ayrz2010 2017-3-23 11:11
基本上玩串口的都离不开modbus开发,很多人觉得简单,从网上随便找资料看看,其实不太系统, Modbus应用和开发的过程中别别扭扭,遇到各种坑搞不定,耽误事情和时间。 个人觉得有2本书可以参考看看。 1)《 从Modbus到透明就绪 》,机工社出版,应用为主。 《从Modbus到透明就绪:施耐德电气工业网络的协议、设计、安装和应用》分为5大部分12章, 第1部分介绍了施耐德电气公司协同自动化的战略;第2部分介绍了Modbus协议和串行链路的物理实现; 第3部分介绍了ModbusPlus工业令牌网络的设计和安装;第4部分介绍了ModbusTCP和透明就绪工业以太网的规划、 选型、安装和服务;第5部分介绍了施耐德电气公司的工业网络在工业领域里的应用。 2)《 Modbus软件开发实战指南 》,清华出版社出版,开发为主。 内容着重讲述如何快速入门并精通Modbus软件开发技术, 适用于初学Modbus 通信 协议的读者,可以看看。 有这两本参考书,认认真真的学习一下,modbus就应该完全掌握了。 个人意见供参考。
966 次阅读|0 个评论
分享 485通信是一种半双工通信
热度 1 hugo0chen 2017-1-11 14:08
公司的一款产品,使用485自动收发电路,测试的时候,接收和发送的内容是错误的,但是电路在其它产品上是ok的。 使用MCU的串口去和485进行数据通信,发送单字节内容,数据正常;发送多字节内容,数据错误。485电路和MCU的串口断开后测试,各自功能验证,收发数据正常。以为是电路问题,尝试在485和串口之间上下拉电阻,串接电阻等方法,现象依旧。后来同事提点,原来时485的使用搞错了。 发送多字节数据的时候,不能够进行数据接收任务,这样误把485当作全双工使用,其实485是半双工的通信方式。 485是一主多从的通信方式,主机查询从机时,对应的从机进行作答,其它从机不能进行数据发送任务,等当前从机发送完后,其它从机在主机呼叫后才可以进行作答。 一开始的方向是怀疑MCU程序中串口的配置初始化有问题,后来怀疑硬件电路问题,最后才找到原因,485的通信机制搞错了。好几天的事情,终于解决了,没文化真可怕。
个人分类: 硬件|2220 次阅读|1 个评论
分享 KW41Z:真正的单芯片多协议无线通信MCU + 恩智浦KW41Z有奖创意征集令高能来袭
linghz 2017-1-5 09:15
KW41Z:真正的单芯片多协议无线通信MCU + 恩智浦KW41Z有奖创意征集令高能来袭 +http://www.eeworld.com.cn/huodong/201611_NXPKW41ZActivity1/index.html
425 次阅读|0 个评论
分享 CC3200 与 ESP8266之间通信(MSP430G2553)
快乐无敌 2016-10-10 18:53
CC3200 与 ESP8266之间通信(MSP430G2553)
本人 新手,请多多指教。
个人分类: CC3200 ESP8266|469 次阅读|0 个评论
分享 关于STM32和蓝牙51822芯片通信调试不通的问题
lingouapple 2016-4-13 14:59
关于STM32和蓝牙51822芯片通信调试不通的问题, 最近软件工程师一直在调试SPI通信问题,一直调试不同,原因是STM32只烧录了系统,STM32中的程序是在系统中运行,导致不兼容二同行失败。 在查找问题的过程中,发现51822(MASTER)驱动限流只有0.2MA左右,驱动非常的弱,怀疑是驱动弱造成的,虽然实际不是这个原因,但是在电路设计的时候,需要充分考虑到MCU驱动能力的问题,所以视情况而定,是否需要添加驱动电路,驱动电路可以是三极管(MOS)转换电路,也可以是集成电平转换芯片。
668 次阅读|0 个评论
分享 线程间通信的定义及全局变量的方法
farsight2009 2016-2-23 15:20
  作者:华清远见讲师   多进程和多线程是系统执行多任务机制的重要手段,多任务同时进行自然少不了相互之间的通信工作。下面先将线程间的通信方式总结一下,便于大家对比学习。   首先来说线程间的通信。因为多个线程是共享进程的空间的,所以线程之间的通信比较简单,主要是利用全局变量的方法。全局变量对进程内的的所有线程都是可见的,所以多个线程可以通过操作全局变量达到相互通信的效果。但是这也存在一个问题,就是 “ 资源 ” 的竞争。   这里所说的资源指的就是全局变量,正是因为这种竞争 ( 因为多线程是同时运行的,而我们往往不会去控制线程运行的顺序,不然也不会用多线程了 ) ,导致可一些我们不愿见到的结果,所以我们每个线程对全局变量的操作都希望是原子性的。   为了解决这个问题在线程见引入了三种同步互斥机制,分别是信号量,互斥锁,条件变量。   具体的函数应用如下:   信号量    #include    int sem_init(sem_t *sem, int pshared, unsigned int value);   功能:信号量的初始化。   参数:    sem :就是信号量的标识符    pshared: 0, 表示该信号量用于线程之间的通信。   非 0 , 表示该信号量用于进程程之间的通信。    value: 非负的整数,就是信号量的初值。   如果为 0 , 表示没有资源。    int sem_wait(sem_t *sem);   功能:阻塞申请信号量资源, 当信号量的值等于 0 时,睡眠等待。   一旦申请成功,那么信号量的值就会被减 1.   参数: sem :    int sem_trywait(sem_t *sem);   功能:非阻塞申请信号量资源,如果申请不到资源,那么该函数立刻返回。    int sem_post(sem_t *sem);   功能:释放信号量资源   释放成功,信号量的值加 1.    int sem_getvalue(sem_t *sem, int *svalue);   功能:获得当前信号量的值。   参数: sem, 指定要获得的信号量    svalue, 用于保存获得的信号量的值。    int sem_destroy(sem_t *sem);   功能:销毁无名信号量。   线程互斥锁    int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);   功能:产生一把锁   参数: mutex : 线程锁的标识符    attr : 设置线程锁的属性,通常为 NULL 。    pthread_mutex_t lock;    pthread_mutex_init(lock, NULL);    int pthread_mutex_lock(pthread_mutex_t *mutex);   功能:上锁, 阻塞等待,直到能够得到这把锁。    int pthread_mutex_unlock(pthread_mutex_t *mutex);   功能 : 解锁。    int pthread_mutex_destroy(pthread_mutex_t *mutex);   功能:就是销毁一把锁。   条件变量:    int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);   功能:初始化条件变量。   参数: cond: 条件变量的标识符    atrr :条件变量的属性,通常为 NULL 。    pthread_cond_t cond;    pthread_cond_init(cond, NULL);    int pthread_cond_signal(pthread_cond_t *cond);   功能:就是给一个需要该条件变量的线程发送唤醒的信号。    int pthread_cond_broadcast(pthread_cond_t *cond);   功能:给所有需要该条件变量的线程都发送唤醒信号。    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);   功能:就是导致线程睡眠在此函数上,直到有线程给它发送条件变量的唤醒信号。   参数: cond :需要改条件变量    mutex: 就是一个锁。    pthread_cond_wait(): 先将锁解开,然后进入睡眠,当被唤醒的时候需要重新加锁 ( 如果此时得不到锁,那么继续睡眠 ) 。    int pthread_cond_destroy(pthread_cond_t *cond);   功能:销毁条件变量。   这些函数的具体用法在上课时候我们已经学过,不再做更为具体的介绍,希望同学们多加练习。这里主要是总结下三者的应用。   这三种机制中,信号量和条件变量属于一种阻塞通知的机制。采用阻塞的方法,让一个进程中只有一个线程能 “ 顺利执行 ” ,执行完毕后再通知其他线程执行。而互斥锁是典型的互斥机制,对资源加以保护,在这期间不允许其他现场对保护的内容进行读写操作。通过信号量和条件变量都可以实现经典的生产者消费者模式。   源文: http://www.embedu.org/column/3170.html    更多优秀技术博文每日更新
个人分类: 嵌入式|694 次阅读|0 个评论
分享 CC2538之TinyOS例程实验:7-blip实验 开始zigbee通信
dan158185 2016-1-5 16:09
前面的6部实验为基本的驱动外设实验,是学习使用基础,实验设备只需要一个cc2538cb节点;从这一部开始实验开始需要两个cc2538cb节点,开始zigbee的无线通信; 此次例程为TinyOS的核心协议栈BLIP,现在的版本是BLIP2.0;大家可以去TinyOS的官网搜索BLIP查看介绍; 如何理解BLIP呢?他的存在意义是什么?我们清楚zigbee到6lowpan的升级,zigbee芯片厂商并没有在硬件部分做6lowpan的压缩解压,这些的完成是纯软件实现的,也就需要 一个 zigbee(IEEE802.15.4)到6lowpan的转换桥梁 ,BLIP最重要的功能就是如此; 例程目录tinyos-main-release_tinyos_2_1_2\apps\cc2538_Test\blip\TestLinkLocal 例程为TinyOS的官方固件的代码,以后大家使用会发现我的这些例程基本不修改官方的例程,方便大家的兼容学习; Makefile文件: view plain copy print ? COMPONENT=TestLinkLocalAppC CFLAGS+=-DUSE_TIMER_HANDLER #CFLAGS+=-DUSE_UART_HANDLER CFLAGS+=-DUSE_RF_HANDLER CFLAGS+=-DNOT_USE_PRINTFC_BUT_USE_PRINT PFLAGS+=-DIN6_PREFIX=\"fec0::\" include$(MAKERULES) CFLAGS+=-DIN6_NO_GLOBAL-DLIB6LOWPAN_HC_VERSION=-1 CFLAGS+=-DPRINTFUART_ENABLED BLIP分为两种模式:短地址(16bit)和IEEE地址(8bytes/64bit)模式,默认采用短地址模式;注意如果后期的实验如边界路由,RPL,CoAP实验;通信都需要选择同一种模式;默认是短地址;大家在完成基本的通讯后可以修改Makefile,尝试IEEE地址模式;具体参考TinyOS官网BLIP文档; TestLinkLocalAppC.nc文件: view plain copy print ? /**Testthelink-localcommunicationintheblipstack */ configurationTestLinkLocalAppC{ }implementation{ componentsMainC,LedsC; componentsTestLinkLocalC; componentsIPStackC; componentsnewTimerMilliC(); componentsnewUdpSocketC(); TestLinkLocalC.Boot-MainC; TestLinkLocalC.SplitControl-IPStackC; TestLinkLocalC.Sock-UdpSocketC; TestLinkLocalC.Timer-TimerMilliC; TestLinkLocalC.Leds-LedsC; componentsStaticIPAddressTosIdC;//UseTOS_NODE_IDinaddress //componentsStaticIPAddressC;//UseLocalIeee154inaddress } TestLinkLocalC.nc文件: view plain copy print ? /******************************************************************* *实验5----zigbeeblip实验 *节点需求数=2 *编译命令makecc2538cbblipid.xx(xx为1~65533) ********************************************************************/ #include"blip_printf.h" #includelib6lowpan/ip.h moduleTestLinkLocalC{ uses{ interfaceBoot; interfaceSplitControl; interfaceUDPasSock; interfaceTimerTMilli; interfaceLeds; } }implementation{ nx_structecho_state{ nx_int8_tcmd; nx_uint32_tseqno; }m_data; enum{ SVC_PORT=10210, CMD_ECHO=1, CMD_REPLY=2, }; /*************************************************** *启动事件 ****************************************************/ eventvoidBoot.booted(){ callSplitControl.start(); m_data.seqno=0; } eventvoidSplitControl.startDone(error_te){ /**开启约2秒的周期性定时器(单位毫秒)Timer**/ callTimer.startPeriodic(2048); /**端口绑定************************************/ callSock.bind(SVC_PORT); } eventvoidSplitControl.stopDone(error_te){} /*************************************************** *Timer定时时间到事件 ****************************************************/ eventvoidTimer.fired(){ structsockaddr_in6dest; inet_pton6("ff02::1",dest.sin6_addr); dest.sin6_port=htons(SVC_PORT); m_data.cmd=CMD_ECHO; m_data.seqno++; /***启动zigbee发送,可以自己修改发送内容和长度*****/ callSock.sendto(dest,m_data,sizeof(m_data)); callLeds.led0Toggle(); } /*************************************************** *接收事件 ****************************************************/ eventvoidSock.recvfrom(structsockaddr_in6*src,void*payload, uint16_tlen,structip6_metadata*meta){ nx_structecho_state*cmd=payload; printf("TestLinkLocalC:recvfrom:"); printf_in6addr(src-sin6_addr); printf("\n"); if(cmd-cmd==CMD_ECHO){ cmd-cmd=CMD_REPLY; callSock.sendto(src,payload,len); callLeds.led1Toggle(); }else{ printf("TestLinkLocalC:replyseqno:%li\n",cmd-seqno); callLeds.led2Toggle(); } } } 如果大家对nesC语法还是不熟悉,可以先去看看前6部实验帖子; nx_struct--- 等价于struct{} __ attribute __ (( packed )) ;是为了兼容平台从8位单片机到32位arm的结构体对齐问题;常常使用的关键字;大家可以使用printf例程 测试一下一个struct里面有unsigned char/long成员后的sizeof打印和nx_struct的sizeof的区别;回忆2530的TinyOS代码,nesC编译成app.c后调用perl脚本对app.c进行转换,其中就必须注释掉了nx_struct生成的 __ attribute __ (( packed )) ; call SplitControl.start();这句代码大家可以使用yeti2插件图形化组件去查看代码(见视频),手动的分析代码;或者生成的app.c去查看,完成了什么,BLIP的地址初始化; 这个例程有视频,没记错应该是第十四部视频; SplitControl.startDone事件开启一个2.048秒的周期性定时器;绑定端口,看到这里大家肯定很熟悉了,Socket的写法 inet_pton6(...)函数,说明一下对于TinyOS我们清楚函数修饰是command,但是由于它支持C的所有特性,所以对于C函数的调用和C语言写法一样,不需要使用call关键字; call Sock.sendto(dest, m_data, sizeof(m_data)); 核心发包部分,也是咱们可以去DIY的,可以DIY内容,接收方解析;比如LED控制,大家可以自己去写; 或者和之前的例程结合一下咱们可以发送采集的片内温度,又或者将串口接收的数据发送,做一个聊天QQ; 例程本质在烧写两个节点完成通信,定义 CMD_ECHO = 1, CMD_REPLY = 2, 发送方发送 CMD_ECHO ,接收方解析后发送回 CMD_REPLY ;例程简单,不做截图了; 需要注意编译命令从这一部开始因为是多节点的通信,我们需要make的时候添加options了,前六部的编译命令是make cc2538cb 这个例程编译命令为 make cc2538cb blip id.xx 如两个节点 我们可以 make cc2538cb blip id.1 烧写 make cc2538cb blip id.2 烧写完成实验; blip的make选项是通知nesC编译器使用blip栈;
个人分类: CC2538之TinyOS例程|856 次阅读|0 个评论
分享 51单片机之串口通信(三)
825cow 2015-12-29 00:21
用串口实现发送和接收同时可操作: 电脑显示结果如图: 源程序: /* 项目名称:串口发送接收实验 项目内容:串口发送接收同时进行, 计算机发送数据给单片机控制P0口,从而控制 LED灯的亮灭,单片机发送数据到计算机,计算机 显示出来 时间:2015年12月23日 项目负责人:YUAN */ #include reg52.h typedef unsigned char uChar8 ; typedef unsigned int uInt16 ; void DelayMS ( uInt16 ValMS ); void UartInit ( void ); //串口初始化 void UartReceiveData ( void ); //接收数据 void UartSendData ( void ); //串口发送数据,即单片机发送数据 void main ( void ) { /*初始化:包括定时器中断的设置, 串口寄存器设置,波特率设置*/ UartInit (); while ( 1 ) { /*接收计算机发送的数据并送给led控制端口*/ UartReceiveData (); UartSendData (); DelayMS ( 500 ); } } void DelayMS ( uInt16 ValMS ) { uInt16 uiVal , ujVal ; for ( uiVal = 0 ; uiVal ValMS ; uiVal ++) for ( ujVal = 0 ; ujVal 113 ; ujVal ++); } void UartInit ( void ) { TMOD = 0x0f ; //只改变要改变的 TMOD |= 0x20 ; //设置定时器0为工作方式2 TL1 = 0xfd ; TH1 = 0xfd ; //设置波特率为9600bps TR1 = 1 ; //允许T1开始计数 SCON = 0x5f ; SCON |= 0x50 ; //设置串口工作在方式1,允许接收数据 } void UartReceiveData ( void ) { //如果接收中断为1,则说明有发送 if ( RI ) { RI = 0 ; P0 = SBUF ; //把发送的数据送给P0控制LED } } void UartSendData ( void ) { static uChar8 num = 0 ; //发送数据,并累加 SBUF = num ; num ++; TI = 0 ; }
个人分类: 51单片机|822 次阅读|0 个评论
分享 51单片机之串口通信(二)
825cow 2015-12-29 00:20
现在来了解一下单片机作为发送程序的讲解: 实现内容:实现单片机从0开始发送,累加,并在电脑串口助手上显示 注意:在显示的时候应该以HEX文件形式显示 /* 项目名称:串口发送实验 项目内容:串口发送数据,从0开始累加。电脑接收并显示 时间:2015年12月23日 项目负责人:YUAN */ #include reg52.h typedef unsigned char uChar8 ; typedef unsigned int uInt16 ; void DelayMS ( uInt16 ValMS ); void UartInit ( void ); //串口初始化 void UartSendData ( void ); //串口发送数据,即单片机发送数据 void main ( void ) { /*初始化:包括定时器中断的设置, 串口寄存器设置,波特率设置*/ UartInit (); while ( 1 ) { /*发送数据到电脑,并在电脑上显示*/ UartSendData (); DelayMS ( 500 ); } } void DelayMS ( uInt16 ValMS ) { uInt16 uiVal , ujVal ; for ( uiVal = 0 ; uiVal ValMS ; uiVal ++) for ( ujVal = 0 ; ujVal 113 ; ujVal ++); } void UartInit ( void ) { TMOD = 0x0f ; //只改变要改变的 TMOD |= 0x20 ; //设置定时器0为工作方式2 TL1 = 0xfd ; TH1 = 0xfd ; //设置波特率为9600bps TR1 = 1 ; //允许T1开始计数 SCON = 0x5f ; SCON |= 0x50 ; //设置串口工作在方式1,允许接收数据 } void UartSendData ( void ) { static uChar8 num = 0 ; //发送数据,并累加 SBUF = num ; num ++; TI = 0 ; }
个人分类: 51单片机|509 次阅读|0 个评论
分享 (转)IIC总线工作原理(1)
825cow 2015-12-29 00:14
转载: http://www.eefocus.com/article/08-07/48416s.html 图11-1给出一个由MCU作为主机,通过IIC总线带3个从机的单主机IIC总线系统。这是最常用、最典型的IIC总线连接方式。 物理结构上,IIC系统由一条串行数据线SDA和一条串行时钟线SCL组成。主机按一定的通信协议向从机寻址和进行信息 传输。在数据传输时,由主机初始化一次数据传输,主机使数据在SDA线上传输的同时还通过SCL线传输时钟。 信息传输的对象和方向以及信息传输的开始和终 止均由主机决定。 每个器件都有一个唯一的地址,而且可以是单接收的器件(例如:LCD驱动器)或者可以接收也可以发送的器件(例如:存储器)。发送器或接收器可以在主模式或从模式下操作,这取决于芯片是否必须启动数据的传输还是仅仅被寻址。 1.总线上数据的有效性 IIC总线是以串行方式传输数据,从数据字节的最高位开始传送,每一个数据位在SCL上都有一个时钟脉冲相对应。在时钟线高电平期间数据线上必须保持稳定 的逻辑电平状态,高电平为数据1,低电平为数据0。只有在时钟线为低电平时,才允许数据线上的电平状态变化,如图11-2所示。 2.总线上的信号 IIC总线在传送数据过程中共有四种类型信号,它们分别是: 开始信号、停止信号、重新开始信号和应答信号 。 开始信号(START):如图11-3所示,当SCL为高电平时,SDA由高电平向低电平跳变,产生开始信号。当总线空闲的时候,例如,没有主动设备在使用总线(SDA和SCL都处于高电平),主机通过发送开始(START)信号建立通信。 停止信号(STOP):如图11-3所示,当SCL为高电平时,SDA由低电平向高电平跳变,产生停止信号。主机通过发送停止信号,结束数据通信。 重新开始信号(Repeated START):在IIC总线上, 由主机发送一个开始信号启动一次通信后,在首次发送停止信号之前,主机通过发送重新开始信号,可以转换与当前从机的通信模式 , 或是切换到与另一个从机通信 。如图11-3所示,当SCL为高电平时,SDA由高电平向低电平跳变,产生重新开始信号,它的本质就是一个开始信号。 应答信号(A): 接收数据的IC在接收到8位数据后,向发送数据的IC发出的特定的低电平脉冲。 每一个数据字节后面都要 跟一位应答信号,表示已收到数据。应答信号在第9个时钟周期出现, 这时发送器必须在这一时钟位上释放数据线, 由接收设备拉低SDA电平来产生应答信号,由 接收设备保持SDA的高电平来产生非应答信号(A(—)),如图11-4所示。所以, 一个完整的字节数据传输需要9个时钟脉冲 。如果从机作为接收方向主机 发送非应答信号,这样,主机方就认为此次数据传输失败;如果是主机作为接收方,在从机发送器发送完一个字节数据后,发送了非应答信号,从机就认为数据传输 结束,并释放SDA线。不论是以上哪种情况都会终止数据传输,这时,主机或是产生停止信号释放总线,或是产生重新开始信号,开始一次新的通信。开始信号、 重新开始信号和停止信号都是由主控制器产生,应答信号由接收器产生,总线上带有IIC总线接口的器件很容易检测到这些信号。 3.总线上数据传输格式 一般情况下,一个标准的IIC通信由四部分组成:开始信号、从机地址传输、数据传输、停止信号。 由主机发送一个开始信号,启动一次IIC通信;在主机对从机寻址后,再在总线上传输数据。IIC总线上传送的每一个字节均为8位,首先发送的数据位为最高 位,每传送一个字节后都必须跟随一个应答位,每次通信的数据字节数是没有限制的;在全部数据传送结束后,由主机发送停止信号,结束通信。 图11-5所示,时钟线为低电平时数据传送将停止进行。这种情况可以用于当接收器接收到一个字节数据后要进行一些其它工 作而无法立即接收下一个数据时,迫使总线进入等待状态,直到接收器准备好接收新数据时,接收器再释放时钟线使数据传送得以继续正常进行。例如,当接收器接 收完主控制器的一个字节数据后,产生中断信号并进行中断处理,中断处理完毕才能接收下一个字节数据,这时接收器在中断处理时将钳住SCL为低电平,直到中 断处理完毕才释放SCL。 4.IIC总线寻址约定 为了消除IIC总线系统中主控器与被控器的地址选择线,最大限度地简化总线连接线,IIC总线采用了独特的寻址约定,规定了开始信号后的第一个字节为寻址字节,用来寻址被控器件,并规定数据传送方向。 在IIC总线系统中,寻址字节由被控器的七位地址位(它占据了D7-D1位)和一位方向位(为D0位)组成。 方向位为0时表示主控器将数据写入被控器,为 1时表示主控器从被控器读取数据。 主控器发送开始信号后,立即发送寻址字节,这时,总线上的所有器件都将寻址字节中的7位地址与自己器件地址比较。如果两 者相同,则该器件认为被主控器寻址,并发送应答信号,被控器根据读,写位确定自身是作为发送器还是接收器。 主器件作为被控器时,其7位从地址在IIC总线地址寄存器中给定,为纯软件地址。而非单片机类型的外围器件地址完全由器件类型与引脚电平给定。IIC总线系统中,没有两个从机的地址是相同的。主控器不应该传输一个和它本身的从地址相同的地址。 5.主机向从机读写1个字节数据的过程 如图11-6所示,主机要向从机写1个字节数据时, 主机首先产生START信号,然后紧跟着发送一个从机地址,这个地址共有7位,紧接着的第8位是数据方 向位(R/W),0表示主机发送数据(写),1表示主机接收数据(读), 这时候主机等待从机的应答信号(A),当主机收到应答信号时,发送要访问的地址, 继续等待从机的应答信号,当主机收到应答信号时,发送1个字节的数据,继续等待从机的应答信号,当主机收到应答信号时,产生停止信号,结束传送过程。 如图11-7所示,主机要从从机读1个字节数据时,主机首先产生START信号,然后紧跟着发送一个从机地址,注意此时该地址的第8位为0,表明是向从机 写命令,这时候主机等待从机的应答信号(A),当主机收到应答信号时,发送要访问的地址,继续等待从机的应答信号,当主机收到应答信号后,主机要改变通信 模式(主机将由发送变为接收,从机将由接收变为发送)所以主机发送重新开始信号,然后紧跟着发送一个从机地址,注意此时该地址的第8位为1,表明将主机设 置成接收模式开始读取数据,这时候主机等待从机的应答信号,当主机收到应答信号时,就可以接收1个字节的数据,当接收完成后,主机发送非应答信号,表示不 在接收数据,主机进而产生停止信号,结束传送过程。
个人分类: 51单片机|720 次阅读|0 个评论
分享 【槛】STM8S103F3P的IIC通信
swisor 2015-9-4 17:04
经过了一天的调试,还是没有克服题述问题,继续下去也是浪费时间。就先把这道槛记录下来,留待下次再说吧! 硬件: 1.STM8S103F3P焊转接板;加Vcap电容;其它元件都没有; 2.AT24C02焊转接板,1、2、3、4脚焊一起;其它元件都没有; 3.I2C_SDA,I2C_SCL用4K7接+3.3V/+5V; 软件: 基于STM8S标准库所带的“I2C_EEPROM”例程,并加以修改,编译通过; 问题: 读写不成功,问题待查。
1321 次阅读|0 个评论
分享 modbus_主从机测试_支持TCP/RTU(转载)
chzfmx 2015-7-26 14:32
Modbus是一种串行通信协议,是Modicon于1979年为使用可编程逻辑控制器PLC而发表的. MODBUS是工业领域通信协议的业界标准,并且现在是工业电子设备之间相当常用的连接方式. Modbus比其他通信协议使用的更广泛的主要原因有: 1)公开发表并且无版税要求 2)相对容易的工业网络部署 3)对供应商来说,修改移动原生的位元或字节没有很多限制 Modbus允许多个设备连接在同一个网络上进行通信,举个例子,一个由测量温度和湿度的装置,并且将结果发送给计算机. 在数据采集与监视控制系统SCADA中,Modbus通常用来连接监控计算机和remote terminal unit (RTU). 细节可以参考wiki百科或相关资料,总的来讲modbus是一个非常靠谱的工业上大量使用的应用层通讯协议,能够让各个厂家的设备能够通讯,只要被支持就可以了。 一、协议版本 Modbus协议目前存在用于串口、以太网以及其他支持互联网协议的网络的版本.大多数Modbus设备通信通过串口EIA-485物理层进行. 对于串行连接,存在两个变种,它们在数值数据表示不同和协议细节上略有不同.Modbus RTU是一种紧凑的,采用二进制表示数据的方式. Modbus ASCII是一种人类可读的,冗长的表示方式.这两个变种都使用串行通讯serial communication方式. RTU格式后续的命令/数据带有循环冗余校验的校验和,而ASCII格式采用纵向冗余校验的校验和. 被配置为RTU变种的节点不会和设置为ASCII变种的节点通信,反之亦然。 对于通过TCP/IP的连接,存在多个Modbus/TCP变种,这种方式不需要校验和的计算. 对于所有的这三种通信协议在数据模型和功能调用上都是相同的,只有封装方式是不同的. Modbus有一个扩展版本Modbus Plus(Modbus+或者MB+),不过此协定是Modicon专有的和Modbus不同. 它需要一个专门的协处理器来处理类似HDLC的高速令牌旋转,它使用1Mbit/s的双绞线,并且每个节点都有转换隔离装置,是一种采用转换/边缘触发而不是电压/水平触发的装置. 连接Modbus Plus到计算机需要特别的接口,通常是支持ISA,PCI或者PCMCIA总线的板卡. 二、通信和设备 Modbus协议是一个master/slave架构的协议,有一个节点是master节点,其他使用Modbus协议参与通信的节点是slave节点. 每一个slave设备都有一个唯一的地址,在串行和MB+网络中,只有被指定为主节点的节点可以启动一个命令. 在以太网上,任何一个设备都能发送一个Modbus命令,但是通常也只有一个主节点设备启动指令. 一个ModBus命令包含了打算执行的设备的Modbus地址,所有设备都会收到命令,但只有指定位置的设备会执行及回应指令. 地址0例外,指定地址0的指令是广播指令,所有收到指令的设备都会执行,不过不回应指令. 所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏. 基本的ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据. 有许多modems和网关支持Modbus协议,因为Modbus协议很简单而且容易复制.它们当中一些为这个协议特别设计的. 有使用有线、无线通信甚至短消息和GPRS的不同实现,不过设计者需要克服一些包括高延迟和时序的问题. 相关说明,图片形式,下面会有用的,直观一点吧: modbus栈结构 modbus帧,这个好好看看,下面调试会用到 典型的cs结构 公共功能码 三、libmodbus库安装 1、下载源码包libmodbus-3.0.6.tar.gz http://libmodbus.org/download/ 2、libmodbus移植 1)交叉编译--prefix参数 嵌入式开发板: # ./configure --build=i686 --host=arm-linux --enable-static --prefix=$(pwd)/libmodbus-install # make # make install 复制代码 2)如果在嵌入式开发板上运行类似unit-test-xxx测试程序时,首先要测试tcp的就要修改两个文件中的IP地址,默认是回环测试的 其次要测试rtu的就要修改两个文件中的串口设备文件名,嵌入式开发板上一般是ttySx,我们的板子是ttySACx 如下位置: unit-test-server.c if (use_backend == TCP) { ctx = modbus_new_tcp("192.168.1.200", 1502); query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); } else if (use_backend == TCP_PI) { ctx = modbus_new_tcp_pi("::0", "1502"); query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); } else { ctx = modbus_new_rtu("/dev/ttySAC1", 115200, 'N', 8, 1); modbus_set_slave(ctx, SERVER_ID); query = malloc(MODBUS_RTU_MAX_ADU_LENGTH); } 复制代码 unit-test-client.c if (use_backend == TCP) { ctx = modbus_new_tcp("192.168.1.200", 1502); } else if (use_backend == TCP_PI) { ctx = modbus_new_tcp_pi("::1", "1502"); } else { ctx = modbus_new_rtu("/dev/ttySAC1", 115200, 'N', 8, 1); } 复制代码 3)在tests目录下的类似unit-test-server这个不是可执行文件,而是一个脚本. 他会调用tests目录下的.lib/下的unit-test-server可执行文件,在PC中需要执行对应的脚本文件,而在嵌入式平台上直接执行tests/.lib可执行文件. 默认生成的测试可执行文件是在隐藏文件夹中的如下操作后可在samba映射中看到 # cd ./tests/ # cp .lib/ test-bin/ # cd test-bin/ 复制代码 4)以上为基本的测试,如果想实际的使用这个库,可以自行写客户端或者服务器程序,调试可以使用对应的Modbus Poll/Slave这是windows下的可视化调试工具. 四、windows下的可视化调试软件 主要两个软件modbus poll和modbus slave,当然如果想先了解modbus通讯协议可以参考协议spec然后用vspd来连接这两个软件,先在pc上面做一些基础的实验,我想是个很好的入门方法。 注意以下软件仅仅用于学习评估,安装测试后删除。 安装软件如下: VSPD PC上测试软件 注意这里我们课使用localhost作为测试,选择tcp方式,方便一点不需要vspd的 串口的连接方式 五、libmodbus测试程序 可以先在板子上面测试,如下 server程序 client测试 测试通过 六、使用可视化工具来调试modbus嵌入式程序 这里我偷懒了,直接使用自带的tests下面的程序来演示如何去做这个事情吧,大家可以动手写自己的modbus主机和从机程序了,方法很简单,不懂的看docs下面的文档还有就是tests下面的例子个个都很不错,我这个帖子不是深入的教学帖子,就不进行详细的代码级别的教学了,主要是说个思路大家自己发挥吧,想搞啥搞啥,没有局限,linux是自由的。当然了实际项目完全按照这个步骤来run没问题的。 我们来看一下unit -test-client.c这个文件中的我们来分析的部分,我也只做了这部分与可视化界面的通讯演示 /** COIL BITS **/ /* Single */ rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, ON); printf("1/2 modbus_write_bit: "); if (rc == 1) { printf("OK\n"); } else { printf("FAILED\n"); goto close; } rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits); printf("2/2 modbus_read_bits: "); if (rc != 1) { printf("FAILED (nb points %d)\n", rc); goto close; } if (tab_rp_bits != ON) { printf("FAILED (%0X = != %0X)\n", tab_rp_bits , ON); goto close; } printf("OK\n"); /* End single */ 复制代码 我们看几个函数说明 modbus_new_rtu modbus_set_slave modbus_write_bit 好了需要注意unit_test.h文件中关于server-id和address的定义信息,后面需要用到 #define SERVER_ID 17 #define INVALID_SERVER_ID 18 const uint16_t UT_BITS_ADDRESS = 0x13; const uint16_t UT_BITS_NB = 0x25; const uint8_t UT_BITS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B }; 复制代码 这有两个地址一个是设备地址一个是modbus的地址域,还比较好懂吧,一主多从,典型的rs485通信链路。 测试图,细节可以看图片中的文字说明: 1)设置slave,这里可以理解为是一个服务,是个从机 2)配置通信,注意我使用板子的COM2 3)测试中,打开通信调试,原始数据,可比对前面的帧结构一个个对应上,还有就是后面那副图中的调试数据 4)板子中跑的程序可以理解为主机,他对设备地址为17=0x11的从机进行bits读写操作 转载地址 :http://home.eeworld.com.cn/?252424
个人分类: modbus|4859 次阅读|0 个评论
分享 STM32经四线SPI与OLED通信
热度 1 crystal008 2015-3-27 11:37
STM32经四线SPI与OLED通信
在大多数STM32的OLED驱动例程中,都给出了相关的软件驱动和硬件设计方法,对具体SSD1306的接线以及IO口的初始化未给出详细的说明。可能是我水平有限,未看明白;或者是大师们不屑说这些简单的内容。以下是自己在做OLED驱动的代码和说明,对初次实验者可能有些帮助。 OLED.H文件 #include "oled.h" #include "stdlib.h" #include "sys.h" #include "delay.h" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //STM32开发板 //SSD1306 OLED 驱动代码 //驱动方式:4线SPI串口 //版权所有,盗版必究。 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// #define BITBAND(addr, bitnum) ((addr 0xF0000000)+0x2000000+((addr 0xFFFFF)5)+(bitnum2)) #define MEM_ADDR(addr)*((volatile unsigned long*)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 //IO口操作,只对单一的IO口! //确保n的值小于16! #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n)//输出 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n)//输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)//输出 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n)//输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n)//输出 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n)//输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n)//输出 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n)//输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n)//输出 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n)//输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n)//输出 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n)//输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n)//输出 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n)//输入 //接线方式如下:当然,VCC和GND必须连接,VCC建议连接3.3V #define LCD_SCL PBout(8) //时钟 D0(SCLK) #define LCD_SDA PBout(9) //D1(SDA) 数据 #define LCD_RST PDout(6) //复位RST #define LCD_DCPBout(5) //DC数据/命令控制 extern void LCD_DLY_ms(unsigned int ms); extern void LCD_WrDat(unsigned char dat); extern void LCD_Set_Pos(unsigned char x, unsigned char y); extern void LCD_Fill(unsigned char bmp_dat); extern void LCD_CLS(void); extern void LCD_P6x8Str(unsigned char x,unsigned chary,unsigned char ch ); extern void LCD_P16x16Ch(unsigned char x,unsigned chary,unsigned charN); extern void Draw_BMP(unsigned char x0,unsigned chary0,unsigned char x1,unsigned chary1,unsigned char BMP ) { unsigned char c=0,i=0,j=0; while (ch !='\0') { c =ch -32; if(x126){x=0;y++;} LCD_Set_Pos(x,y); for(i=0;i6;i++) LCD_WrDat(F6x8 ); x+=6; j++; } } /*******************功能描述:显示8*16一组标准ASCII字符串显示的坐标(x,y),y为页范围0~7****************/ void LCD_P8x16Str(unsigned char x,unsigned chary,unsigned char ch !='\0') { c =ch -32; if(x120){x=0;y++;} LCD_Set_Pos(x,y); for(i=0;i8;i++) LCD_WrDat(F8X16 ); LCD_Set_Pos(x,y+1); for(i=0;i8;i++) LCD_WrDat(F8X16 ); x+=8; j++; } } /*****************功能描述:显示16*16点阵显示的坐标(x,y),y为页范围0~7****************************/ void LCD_P16x16Ch(unsigned char x,unsigned chary,unsigned charN) { unsigned char wm=0; unsigned int adder=32*N;// LCD_Set_Pos(x , y); for(wm = 0;wm 16;wm++)// { LCD_WrDat(F16x16 ); adder += 1; } LCD_Set_Pos(x,y + 1); for(wm = 0;wm 16;wm++) // { LCD_WrDat(F16x16 ); adder += 1; } } /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/ void Draw_BMP(unsigned char x0,unsigned chary0,unsigned char x1,unsigned chary1,unsigned char BMP ); } } } //初始化SSD1306 void OLED_Init(void) { GPIO_InitTypeDefGPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 SCLK - PB8SDIN - PB9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //这个频率不能太高,10M我试过,OLED屏显示会有问题 GPIO_Init(GPIOB, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // DC - PB5 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 GPIO_Init(GPIOB, GPIO_InitStructure); // RST - PD6 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOD, GPIO_InitStructure); GPIO_SetBits(GPIOD, GPIO_Pin_6); LCD_SCL=1; LCD_RST=0; LCD_DLY_ms(50); LCD_RST=1; //从上电到下面开始初始化要有足够的时间,即等待RC复位完毕 LCD_WrCmd(0xae);//--turn off oled panel LCD_WrCmd(0x00);//---set low column address LCD_WrCmd(0x10);//---set high column address LCD_WrCmd(0x40);//--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F) LCD_WrCmd(0x81);//--set contrast control register LCD_WrCmd(0xcf); // Set SEG Output Current Brightness LCD_WrCmd(0xa1);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 LCD_WrCmd(0xc8);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 LCD_WrCmd(0xa6);//--set normal display LCD_WrCmd(0xa8);//--set multiplex ratio(1 to 64) LCD_WrCmd(0x3f);//--1/64 duty LCD_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) LCD_WrCmd(0x00);//-not offset LCD_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency LCD_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec LCD_WrCmd(0xd9);//--set pre-charge period LCD_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks Discharge as 1 Clock LCD_WrCmd(0xda);//--set com pins hardware configuration LCD_WrCmd(0x12); LCD_WrCmd(0xdb);//--set vcomh LCD_WrCmd(0x40);//Set VCOM Deselect Level LCD_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02) LCD_WrCmd(0x02);// LCD_WrCmd(0x8d);//--set Charge Pump enable/disable LCD_WrCmd(0x14);//--set(0x10) disable LCD_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5) LCD_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7) LCD_WrCmd(0xaf);//--turn on oled panel LCD_Fill(0x00);//初始清屏 LCD_Set_Pos(0,0); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { /* Add your application code here*/ unsigned char i=0; LED_GPIO_Config(); delay_init(72); //延时初始化 OLED_Init(); //初始化OLED LCD_P8x16Str(28,0,"OLED TEST"); LCD_P8x16Str(20,2,"OLEDDISPLAY"); LCD_P6x8Str(16,5," 315322339@qq.com "); LCD_P6x8Str(34,6,"2014-11-22"); delay_ms(1000); Draw_BMP(0,0,128,8,BMP);//图片显示 delay_ms(1500); //延时1s LCD_Fill(0); while(1) { LED4_OFF; delay_ms(1000); //延时1s LED4_ON; delay_ms(1000); //延时1s for(i=0; i8; i++) { LCD_P16x16Ch(i*16,0,i);//点阵显示 LCD_P16x16Ch(i*16,2,i+8); LCD_P16x16Ch(i*16,4,i+16); LCD_P16x16Ch(i*16,6,i+24); } } }
19479 次阅读|1 个评论
分享 STM32经IIC与OLED通信
crystal008 2015-3-27 11:31
STM32经IIC与OLED通信
最近搞STM32与OLED通信,整合“百家”之言弄出来的,谢谢大家的帮助。以下是STM32经IIC与OLED通信代码,至于 以下数组 extern unsigned charF16x16 ; extern unsigned charBMP ; extern const unsigned charF6x8 ; extern const unsigned charF8X16 ; 数据太大,不便粘贴;如有需要的朋友,可以联系我传给你;目前实验已完成,由于权限的问题,不能上传图片,敬请谅解。 个人感觉IIC通信比四线SPI(见上篇博客)简单,具体体现:硬件、软件和接线都比较少,只代表个人观点;其实如果会的话,应该都差不多。 IIC.h #ifndef __IIC_H #define __IIC_H #ifdef __cplusplus extern "C" { #endif /*************Pin Define***************/ #define SCL_HIGHGPIO_SetBits(GPIOB, GPIO_Pin_8) //LED1点亮//P1OUT|=BIT0 //SCL P1.0 #define SCL_LOW GPIO_ResetBits(GPIOB, GPIO_Pin_8) //P1OUT=~BIT0 #define SDA_HIGHGPIO_SetBits(GPIOB, GPIO_Pin_9) //P1OUT|=BIT1 //SDA P1.1 #define SDA_LOW GPIO_ResetBits(GPIOB, GPIO_Pin_9) //P1OUT=~BIT1 /****************************************************/ void OLED_Initial(void); void IIC_Start(void); void IIC_Stop(void); void Write_IIC_Command(unsigned char IIC_Command); void Write_IIC_Data(unsigned char IIC_Data); void Write_IIC_Byte(unsigned char IIC_Byte); void LCD_Set_Pos(unsigned char x, unsigned char y); void LCD_CLS(void); void LCD_P8x16Str(unsigned char x,unsigned chary,unsigned char ch ); void Draw_BMP(unsigned char x0,unsigned chary0,unsigned char x1,unsigned chary1,unsigned char BMP ) { unsigned char c=0,i=0,j=0; while (ch !='\0') { c =ch -32; if(x126){x=0;y++;} LCD_Set_Pos(x,y); for(i=0;i6;i++) Write_IIC_Data(F6x8 ); x+=6; j++; } } /*******************功能描述:显示8*16一组标准ASCII字符串 显示的坐标(x,y),y为页范围0~7****************/ void LCD_P8x16Str(unsigned char x,unsigned chary,unsigned char ch !='\0') { c =ch -32; if(x120){x=0;y++;} LCD_Set_Pos(x,y); for(i=0;i8;i++) Write_IIC_Data(F8X16 ); LCD_Set_Pos(x,y+1); for(i=0;i8;i++) Write_IIC_Data(F8X16 ); x+=8; j++; } } /*****************功能描述:显示16*16点阵显示的坐标(x,y),y为页范围0~7****************************/ void LCD_P16x16Ch(unsigned char x,unsigned chary,unsigned charN) { unsigned char wm=0; unsigned int adder=32*N;// LCD_Set_Pos(x , y); for(wm = 0;wm 16;wm++)// { Write_IIC_Data(F16x16 ); adder += 1; } LCD_Set_Pos(x,y + 1); for(wm = 0;wm 16;wm++) // { Write_IIC_Data(F16x16 ); adder += 1; } } /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/ void Draw_BMP(unsigned char x0,unsigned chary0,unsigned char x1,unsigned chary1,unsigned char BMP ); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { /* Add your application code here*/ char i; LED_GPIO_Config(); delay_init(72); //延时初始化 OLED_Initial(); LCD_P8x16Str(28,0,"OLED TEST"); LCD_P8x16Str(20,2,"OLEDDISPLAY"); LCD_P6x8Str(16,5,"315322339@qq.com"); LCD_P6x8Str(34,6,"2014-11-22"); delay_ms(1500); //延时1s Draw_BMP(0,0,128,8,BMP);//图片显示 delay_ms(1000); LCD_CLS(); /* Infinite loop */ while(1) { LED4_OFF; delay_ms(500); //延时1s LED4_ON; delay_ms(500); //延时1s for(i=0; i8; i++) { LCD_P16x16Ch(i*16,0,i);//点阵显示 LCD_P16x16Ch(i*16,2,i+8); LCD_P16x16Ch(i*16,4,i+16); LCD_P16x16Ch(i*16,6,i+24); } } }
3901 次阅读|0 个评论
分享 linux进程通信概述
liuzebin9 2015-2-2 13:00
进程通信的目的: 1: 数据传输 一个进程需要将它的数据发送给另一个进程。 2 资源共享 多个进程共享同样的资源。 3 通知事件 一个进程需要向另一个或一组进程发送消息,通知他们发生了某件事情。 4 进程控制 有些进程希望完全控制另一个进程的执行(如 Debug 进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变。 进程通信的发展: 1 : unix 进程间通讯 2 :基于 system V 进程间通讯 3 : POSIX 进程间通讯 进程通信的分类 : 1 :管道和有名管道 2 :信号 3 :消息队列 4 :共享内存 5 :信号量 6 :套接字
个人分类: 嵌入式linux|493 次阅读|0 个评论
分享 51单片机的晶振为何常常使用 11.0592Mhz?
charlion 2014-8-28 09:05
因为对于标准通信速率,使用11.0592Mhz的晶振可以得到精准的数值。具体而言如下: 常用波特率通常有:1200、2400、4800、9600,------,若采用晶振12Mhz或6Mhz,计算出的T1定时初值将不是一个整数,这样通信时便会产生积累误差,进而产生波特率误差,影响串行通信的同步性能。 解决方法只有调整单片机的时钟频率,通常采用11.0592Mhz晶振,因为它能非常精确地计算出T1定时器初值,只要是标准通信速率,就可以得到非常准确的数值。
个人分类: 单片机|673 次阅读|0 个评论
分享 串口通信
charlion 2014-8-27 14:06
串口通信
UART(UniversalAsynchronousReceiver/Transmitter,即通用异步收发器)串行通信是单片机最常用的一种通信技术,通常用于单片机和电脑之间以及单片机和单片机之间的通信。 波特率就是发送二进制数据位的速率,习惯上用baud表示,即我们发送一位二进制数据 的持续时间=1/baud。 在UART通信的时候,一个字节是8位,规定当没有通信信号发生时,通信线路保持高电平,当要发送数据之前,先发一位0表示起始位,然后发送8位数据位,数据位是先低后高的顺序,数据位发完后再发一位1表示停止位。这样本来要发送一个字节的8位数据,而实际上我们一共发送了10位,多出来的两位,其中一位起始位,一位停止位。而接收方呢,原本一直保持的高电平,一旦检测到了一位低电平,那就知道了要开始准备接收数据了,接收到8位数据位后,然后检测到停止位,再准备下一个数据的接收。串口数据发送示意图如下: RS232通信接口 : RS232接口一共有9个引脚,分别定义是:1、载波检测DCD;2、接收数据RXD;3、发送数据TXD;4、数据终端准备好DTR;5、信号地线SG;6、数据准备好DSR;7、请求发送RTS;8、清除发送CTS;9、振铃提示RI。我们要让这个串口和我们单片机进行通信,我们只需要关心其中的2脚RXD、3脚TXD和5脚GND即可。 另外,不是所有的电路都是5V代表高电平而0V代表低电平的。对于RS232标准来说,它是个反逻辑,也叫做负逻辑。为何叫负逻辑?它的TXD和RXD的电压,-3V~-15V电压代表是1,+3~+15V电压代表是0。低电平代表的是1,而高电平代表的是0,所以称之为负逻辑。因此电脑的9针RS232串口是不能和单片机直接连接的,需要用一个电平转换 芯片MAX232来完成。MAX232转接图如下: 如此, 就可以实现把标准RS232串口电平转换成我们单片机能够识别和承受的UART0V/5V电平 。 USB转串口通信 : 在电路上添加一个USB转串口芯片,就可以成功实现USB通信协议和标准UART串行通信协议的转换,常用的芯片有CH340T、CH340G、PL2303等。
个人分类: 单片机|1765 次阅读|0 个评论
分享 通信的三种基本类型
charlion 2014-8-25 09:53
常用的通信从传输方向上可以分为单工通信、半双工通信、全双工通信三类。 单工通信就是指只允许一方向另外一方传送信息,而另一方不能回传信息。比如电视遥 控器、收音机广播等,都是单工通信技术。 半双工通信是指数据可以在双方之间相互传播,但是同一时刻只能其中一方发给另外一 方,比如我们的对讲机就是典型的半双工。 全双工通信就发送数据的同时也能够接收数据,两者同步进行,就如同我们的电话一样,我们说话的同时也可以听到对方的声音。
个人分类: 单片机|497 次阅读|0 个评论
分享 单片机通信方面的帖子
热度 1 曹世鹏 2014-8-8 22:55
咱们eeword论坛有没有单片机串口通信方面的帖子呢。我现在搞的51单片机和SIM900A通信的板子玩儿,可是还是没做完。因为虽然SIM900A的数据格式是0D 0A开头,0D 0A结尾。但是它的0D 0A的个数是不固定的。比如说回复OK的时候是两个0D 0A,但是读短信的时候是5组0D 0A。这还都是在关闭回显的情况下作的。即ATE0。我想知道大家在做这种数据包长度不定,包头不定,包尾不定的单片机串口通信项目时是怎么确定这一串数据接收完毕的呢?看到大家好多都在DIY手机,就是用的GSM模块儿和单片机通信的。不知道大家怎么处理这种通信方式的,不知道大家在写程序的时候画不画流程图。像做无线透传项目的感觉就更神奇了。他是怎么知道这一串数据已经完全接收完了呢。太多的疑问在我脑中。
个人分类: 学习笔记。|1358 次阅读|5 个评论
分享 CRC-16校验原理
muxb 2014-8-5 20:28
最详细易懂的CRC-16校验 原理 (附源程序) 1 、循环校验码(CRC码): 是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。 2 、生成CRC码的基本 原理 : 任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x 6 +x 4 +x 2 +x+1,而多项式为x 5 +x 3 +x 2 +x+1对应的代码101111。 标准CRC生成多项式如下表: 名称 生成多项式 简记式* 标准引用 CRC-4 x4+x+1 3 ITU G.704 CRC-8 x8+x5+x4+1 0x31 CRC-8 x8+x2+x1+1 0x07 CRC-8 x8+x6+x4+x3+x2+x1 0x5E CRC-12 x12+x11+x3+x+1 80F CRC-16 x16+x15+x2+1 8005 IBM SDLC CRC16 -CCITT x16+x12+x5+1 1021ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS CRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS CRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP 3 、CRC-16校验码的使用: 现选择最常用的CRC-16校验,说明它的使用方法。 根据 Modbus协议, 常规485通讯的信息发送形式如下: 地址 功能码 数据信息 校验码 1byte 1byte nbyte2byte CRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。 例如: 信息字段代码为: 1011001,校验字段为:1010。 发送方 :发出的传输字段为: 1 0 1 1 0 0 1 1 0 10 信息字段 校验字段 接收方 :使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。 4 、CRC-16校验码计算方法: 常用查表法和计 算法 。计算方法一般都是: (1)、预置1个16位的寄存器为十六进制FFFF(即全为1),称此寄存器为CRC寄存器; (2)、把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低 8位相异或,把结果放于CRC寄存器,高八位数据不变; (3)、把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位; (4)、如果移出位为0:重复第3步(再次右移一位);如果移出位为1,CRC寄存器与多 项式A001(1010000000000001)进行异或; (5)、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理; (6)、重复步骤2到步骤5,进行通讯信息帧下一个字节的处理; (7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低 字节进行交换; (8)、最后得到的CRC寄存器内容即为:CRC码。 以上计算步骤中的多项式A001是8005按位颠倒后的结果。 查表法是将移位异或的计算结果做成了一个表,就是将0~256放入一个长度为16位的寄存器中的低八位,高八位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到八位全部移出,最后寄存器中的值就是表格中的数据,高八位、低八位分别单独一个表。
个人分类: 经验分享|2428 次阅读|0 个评论

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-5-27 18:05 , Processed in 0.076145 second(s), 26 queries , Gzip On, MemCache On.

Powered by EEWORLD电子工程世界

© 2020 http://bbs.eeworld.com.cn/

返回顶部