2019年3月

嵌入式、物联网技术交流分享

STM32 定时器

预分频器(TIMx_PSC) 预分频器的值 PSC[15:0],计数器的时钟频率 CK_CNT 等于 fCK_PSC / (PSC[15:0] + 1)。也就是说 PSC[15:0] 等于分频数 - 1。 自动重装载寄存器(TIMx_ARR) 自动重装载的值 ARR[15:0],用于作为计数器的初始值(向下计数)或溢出值(向上计数)。下图的 ARR 被设置为 0x36,溢出发生在计数值为 0x36 的后部,所以实际计数了 0x37 个数(从 0 开始)。所以 ARR 的值应该为 计数值 - 1。 PWM PWM 模式 1 在向上计数时,一旦 TIMx_CNT < TIMx_CCR1 时通道 1 为有效电平,否则为 无效电平;在向下计数时,一旦 TIMx_CNT > TIMx_CCR1 时通道 1 为无效电平(OC1REF=0),否 则为有效电平(OC1REF=1)。 PWM 模式 2 在向上计数时,一旦 TIMx_CNT < TIMx_CCR1 时通道 1 为无效电平,否则为 有效电平;在向下计数时,一旦 TIMx_CNT > TIMx_CCR1 时通道 1 为有效电平,否则为无效电 平。 CC1P:输入/捕获 1 输出极性(Capture/Compare 1 output polarity) CC1 通道配置为输出: 0:OC1 高电平有效 TIM_OCPolarity_High 1:OC1 低电平有效 TIM_OCPolarity_Low 例如: TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PMW模式1(向上计数时CNT < CCR2时输出低电平) TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period / 2; //50%占空比 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //低电平为有效电平 TIM_OC2Init(TIM2, &TIM_OCInitStructure)...

铁电(FRAM)随机存取存储器 MB85RC64

存储空间:8KB 不同于 Flash 和 E2PROM,无需写等待时间。 使用 I2C 总线,频率可到 400KHz。 数据可以保持 10 年。 WP 脚为高电平时处于写保护状态,默认已内部下拉到地。 器件地址为 7bits 模式,高4位为设备类型码(1010b),低 3 位由硬件引脚 A2、A1、A0 指定(已内部下拉),与 MB85RC16 是不同的。这使得一条总线上可以挂载多个同型号的器件。 存储器的写与读速度是相同的,所以无需在写的时候额外添加等待时间。 8KB 存储空间的有效地址为 13 位。 随机读: 写字节: 写页: 存储器的页指的是整个 8KB 的存储区,没有划分为若干页。当地址空间溢出时回回滚到 000H 继续增长...

I2C 通信协议

I2C(Inter-Integrated Circuit,又常写作 IIC、$I^2C$)是一种广泛应用于数字电路中的串行通信协议。这种通信协议由 Philips 公司(现在的 NXP 公司)在 20 世纪 80 年代开发,旨在解决多个芯片间的通信问题。I2C 通信协议具有简单、高可靠性和灵活性的特点,因此被广泛应用于各种不同领域的电子设备中。 I2C 协议使用两根线进行数据传输,分别是 SDA(Serial Data Line)和 SCL(Serial Clock Line)。数据在 SDA 线上传输,而时钟同步则由 SCL 线提供。这两根线在通信过程中通过电平变化来传输数据,并且都有上拉电阻。 在 I2C 通信中,有两个主要的参与者角色:主设备(Master)和从设备(Slave)。主设备是 I2C 总线的控制者,负责发起通信和发送指令;从设备则根据主设备的指令执行相应的操作并返回数据。 I2C 通信协议的基本操作包括起始条件和停止条件。起始条件是主设备发起通信的标志,它的产生是通过在 SCL 线保持高电平的同时将 SDA 线从高电平拉低。停止条件是通信结束的标志,在 SCL 线保持高电平的同时将 SDA 线从低电平拉高。 在起始条件之后,主设备会发送一些控制字节来选择特定的从设备进行通信。这些控制字节通常包括从设备的地址和读/写控制位。一旦从设备被选择,数据传输可以开始。数据的传输采用字节为单位,每个字节的传输分为数据传输和应答两个部分。 此外,I2C 协议还规定了数据有效性、地址及数据方向、应答信号和非应答信号等方面的细节,以确保通信的准确和可靠。 读写标志位:1 为读,0 为写。 注意: SDA 使用 GPIO 的 OD 模式时,在读前不需要将 GPIO 切换为输入模式,可以直接读取,但需要在读前将其输出电平置为高,这时由于时开漏状态,是由外部上拉电阻将总线拉高的,这时从设备才可以将总线拉低。如果主设备输出低电平则总线一直被主设备强拉低而使从设备不能正常输出高电平,从而使读通信不能正常进行。 主机在收完从机的 ACK 后要把 SCL 拉低,否则从机一直保持输出电平(SCL 高电平是从设备电平不能变化),比如 ACK 时一直输出低电平,NACK 时一直输出高电平,主机的 Sr 开始信号不能够使从机重新开始。 SDA 线上的数据在时钟“高”期间必须是稳定的,只有当 SCL 线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。 数据有效性 I2C 使用 SDA 信号线来传输数据,使用 SCL 信号线进行数据同步。SDA 数据线在 SCL 的每个时钟周期传输一位数据。传输时,SCL 为高电平的时候 SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL 为低电平时,SDA 的数据无效,一般在这个时候 SDA 进行电平切换,为下一次表示数据做好准备。 重启动信号 在主控器控制总线期间完成了一次数据通信(发送或接收)之后,如果想继续占用总线再进行一次数据通信(发送或接收),而又不释放总线,就需要利用重启动 Sr 信号时序。重启动信号 Sr 既作为前一次数据传输的结束,又作为后一次数据传输的开始。利用重启动信号的优点是,在前后两次通信之间主控器不需要释放总线,这样就不会丢失总线的控制权,即不让其他主器件节点抢占总线。 Sr 的型号与 S 是完全一样的,后面要重新发送器件地址,与S后的逻辑完全一致。 I2C 有 7 位和 10 位两种地址模式 I2C 规范保留了两组和 8 个地址,1111XXX 和 0000XXX。这些地址用于特殊用途。 从机地址+R/W 描述 0000 0000 呼叫地址 0000 0001 起始字节 0000 001X CBUS地址 0000 010X 保留供不同的总线格式 0000 011X 保留将来用 0000 1XXX HS模式主机码 1111 0XXX 10位从机地址 1111 1XXX 保留将来用 I2C 总线的 10bit 寻址和 7bit 寻址是兼容的,这样就可以在同一个总线上同时使用 7bit 地址和 10bit 地址模式的设备,在进行 10bit 地址传输时,第一字节是一个特殊的保留地址来指示当前传输的是 10bit 地址...

铁电(FRAM)随机存取存储器 MB85RC16

存储空间:2KB 不同于 Flash 和 E2PROM,无需写等待时间。 使用 I2C 总线,频率可到 1MHz。 数据可以保持 10 年。 WP 脚为高电平时处于写保护状态,默认已内部下拉到地。 器件地址为 7bits 模式,高 4 位为设备类型码(1010b),低 3 位为存储地址的高 3 位。 写字节: 写页: 存储器的页指的是整个 2KB 的存储区,没有划分为若干页。当地址空间溢出时回回滚到 000H 继续增长。 读当前地址: 上一次操作完成后存储器的地址仍被保留再地址缓冲器中,这时使用读当前地址命令可以直接读到缓冲器缓存的地址(n + 1)指向的存储区。地址缓冲器中的地址在上电后是不确定的。11 位地址的高三位是需要指定的。 随机读取: 读取可以持续进行,地址溢出后会回滚到000...

AT24CXX EEPROM 存储器芯片

AT24CXX 是 ATMEL 公司的两线制(I2C 或 IIC)汽车温度级串行 EEPROM 存储器,AT24C01A、AT24C02、AT24C04、AT24C08A、AT24C16A 等多款型号,他们的存储空间分别为 128 字节、256 字节、512 字节、1024 字节、2048 字节。 I2C 时钟支持 400KHz。 I2C 器件基础地址(ID)为:0x50,可以通过部分引脚配置扩展地址,从而可以实现在一条总线上挂载多片同类型芯片的目的。 读操作支持随机寻址并连续读多字节数据(地址自动增加,当到达边界时会回滚至 0 地址重新增长)。 写操作支持单字节写入和页写入。1K/2Kbits 芯片页空间为 8 字节,4K/8K/16Kbits 芯片页空间为 16 字节。当连续写入时地址会自动增加,但地址会在页内回滚循环。收到 I2C 停止信号时开始写入,写入周期为 5m...

RT-Thread 邮箱与消息队列

邮箱 RT-Thread 操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的 4 字节内容(针对 32 位处理系统,指针的大小即为 4 个字节,所以一封邮件恰好能够容纳一个指针)。典型的邮箱也称作交换消息。 邮件发送不具有加急(插队)的功能。 静态邮箱初始化 初始化前资源要静态地创建。 rt_err_t rt_mb_init(rt_mailbox_t mb, const char *name, void *msgpool, rt_size_t size, rt_uint8_t flag) 静态邮箱脱管 把静态初始化的邮箱对象从内核对象管理器中脱离。 rt_err_t rt_mb_detach(rt_mailbox_t mb) 创建邮箱 动态地创建邮箱并初始化。 rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) 删除邮箱 脱管邮箱并释放动态资源,与 rt_mb_create 配合使用。 rt_err_t rt_mb_delete(rt_mailbox_t mb) 发送邮件 rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value) 函数调用了rt_mb_send_wait,timeout = 0 以等待方式发送邮件 邮箱满时等待。 rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_uint32_t value, rt_int32_t timeout) 接收邮件 支持空等待。 rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_uint32_t *value, rt_int32_t timeout) 邮箱控制 不常用。 rt_err_t rt_mb_control(rt_mailbox_t mb, rt_uint8_t cmd, void *arg) 2.1.0 版 支持的命令 RT_IPC_CMD_RESET(复位邮箱) timeout 支持以下宏: #define RT_WAITING_FOREVER -1 /**< Block forever until get resource. */ #define RT_WAITING_NO 0 /**< Non-block. */ 消息队列 消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。消息队列是一种异步的通信方式。 很遗憾的是消息队列不支持发送阻塞模式(像邮箱那样的发送等待)。 消息队列初始化 静态创建。 rt_err_t rt_mq_init(rt_mq_t mq, const char *name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag) 消息队列脱管 rt_err_t rt_mq_detach(rt_mq_t mq) 动态创建消息队列 rt_mq_t rt_mq_create(const char *name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag) 删除消息队列 rt_err_t rt_mq_delete(rt_mq_t mq) 发送消息到队列 线程或者中断服务程序都可以给消息队列发送消息。当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。 rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size) 发送紧急消息到队列 发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。 rt_err_t rt_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size) 接收消息 当消息队列中有消息时,接收者才能接收消息,否则接收者会根据超时时间设置,或挂起在消息队列的等待线程队列上,或直接返回。 rt_err_t rt_mq_recv(rt_mq_t mq, void *buffer, rt_size_t size, rt_int32_t timeout) 消息队列控制 rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void *arg) 支持的命令有:RT_IPC_CMD_RESET(复位) 区别 邮箱只能传4字节的值,消息队列可以传递更长的值; 邮箱有发送等待功能,消息队列没有; 消息队列有紧急消息功能,邮箱没有紧急邮件的功能...