我已经开始阅读电子产品和嵌入式软件。最近我一直在看IC,特别是换档寄存器。我认为学习更多关于串行通信和移位寄存器的好方法是实现移位寄存器的内部逻辑。
我选择的是74HC595。
我已经这样做了,所以它将类似于将不同的CPU引脚设置为高或低。假设操作IC的每个功能都是连接到IC的CPU引脚的值。
当然,这可以通过简单易用的包装器来简化,所以您只需调用一个函数,说明在寄存器上设置哪个引脚是低的还是高的。但这不是重点。
#include <stdio.h>
#include "../src/ic/ic_74hc595.h"
int main()
{
struct ic_74hc595 ic = {0, 0, LOW, LOW, LOW};
/* Initial value check. Should be 0 */
printf("ic value: %u\n", ic.value);
/* Set the first bit to 1. */
ic_set_stcp(&ic, HIGH);
ic_set_ds(&ic, HIGH);
ic_set_stcp(&ic, LOW);
printf("ic value: %u\n", ic.value);
/* Iterate to third bit */
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
/* Set it to 1 */
ic_set_stcp(&ic, HIGH);
ic_set_ds(&ic, HIGH);
ic_set_stcp(&ic, LOW);
printf("ic value: %u\n", ic.value);
/* Iterate to last bit */
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
ic_set_shcp(&ic, HIGH);
ic_set_shcp(&ic, LOW);
/* Set it to 1 */
ic_set_stcp(&ic, HIGH);
ic_set_ds(&ic, HIGH);
ic_set_stcp(&ic, LOW);
printf("ic value: %u\n", ic.value);
/* Reset */
ic_set_mr(&ic, LOW);
printf("ic value %u\n", ic.value);
return 0;
}#ifndef IC_74HC595_H_
#define IC_74HC595_H_
#include <stdint.h>
#define HIGH 1
#define LOW 0
typedef _Bool bit;
/**
* The 74HC595 ic's internal state representation.
*
* value - The 8-bit value which represents the paralell out data
* i - The current bit which is iterated to
* shcp - The shift clock input, which is used to iterate the 8 bits. Each time it switches from LOW (0) to HIGH (1) it iterates one bit.
* stcp - The register clock input, which is used to tell the register to accept data. LOW (0) means it doesn't accept data, HIGH (1) means it does accept data.
* ds - Serial data, which is used to tell which value the current bit should have; LOW (0) or HIGH (1).
*/
struct ic_74hc595{
uint8_t value;
uint8_t i;
bit shcp;
bit stcp;
bit ds;
};
void ic_set_shcp(struct ic_74hc595 *ic, bit shcp);
void ic_set_stcp(struct ic_74hc595 *ic, bit stcp);
void ic_set_ds(struct ic_74hc595 *ic, bit ds);
void ic_set_mr(struct ic_74hc595 *ic, bit mr);
#endif#include "ic_74hc595.h"
/**
* Changes the shcp clock to the given value
*
* @param ic
* The ic to change state and value of
*
* @param shcp
* The shift clock input
*/
void ic_set_shcp(struct ic_74hc595 *ic, bit shcp)
{
if (ic->shcp == LOW && shcp == HIGH) {
ic->shcp = HIGH;
ic->i++;
}else if (ic->shcp == HIGH && shcp == LOW){
ic->shcp = LOW;
}
}
/**
* Changes the stcp clock to the given value
*
* @param ic
* The ic to change state and value of
*
* @param stcp
* The register clock input
*/
void ic_set_stcp(struct ic_74hc595 *ic, bit stcp)
{
if (ic->stcp != stcp) {
ic->stcp = stcp;
}
}
/**
* Gives the current bit a new value if stcp is HIGH.
*
* @param ic
* The ic to change state and value of
*
* @param ds
* The data input
*/
void ic_set_ds(struct ic_74hc595 *ic, bit ds)
{
if (ic->ds != ds) {
ic->ds = ds;
}
if (ic->stcp == LOW) {
return;
}
ic->value |= (ds << ic->i);
}
/**
* Resets the internal state if mr is LOW.
*
* @param ic
* The ic to change state and value of
*
* @param mr
* The master reset value
*/
void ic_set_mr(struct ic_74hc595 *ic, bit mr)
{
if (mr == LOW) {
ic->value = 0;
ic->i = 0;
ic->shcp = LOW;
ic->stcp = LOW;
ic->ds = LOW;
}
}使用
gcc ./examples/ic_simulator.c ./src/ic/ic_74hc595.c -o ic_simulator -Wall -pedantic我希望得到的反馈如下:
发布于 2012-01-10 20:15:29
好的。把它看作是代码保持器,而不是理解芯片的底层逻辑(这就是现实生活中将要发生的事情)。
函数名看起来有点通用。
您可能需要在它们的前缀加上芯片的名称(C unlink C++不提供函数重载)。这样您就可以提供与一组芯片类似的功能。
从阅读文档看,这看起来不错(不过我必须承认,我不是百分之百确定)。
但是,一个普通的维护者会想知道为什么一半的代码路径什么都不做。
void ic_set_shcp(struct ic_74hc595 *ic, bit shcp)
{
if (ic->shcp == LOW && shcp == HIGH) {
ic->shcp = HIGH;
ic->i++;
}else if (ic->shcp == HIGH && shcp == LOW){
ic->shcp = LOW;
}
}因此,我认为这个函数需要更多的文档(尤其是为什么非状态更改(如果是ic->shcp == shcp)。
下一个函数是否可以不简化(我可能遗漏了什么东西,在这种情况下是注释):
void ic_set_stcp(struct ic_74hc595 *ic, bit stcp)
{
if (ic->stcp != stcp) {
ic->stcp = stcp;
}
}这不等于:
void ic_set_stcp(struct ic_74hc595 *ic, bit stcp)
{
ic->stcp = stcp;
}可以在链接文档中读取函数表(第3页):
FUNCTION TABLE See note 1.
我看到了一组输入和一组输出。我还看到,输出取决于输入状态的变化。因此,我希望我的函数能够镜像这个表(也许这有点低?)。
因此,我本以为会有这样的界面:
typedef enum { Low, NoCharge, High, HighImpedence} PinState;
typedef enum { Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q7Dash} OutputPinID;
struct ic_74hc595 { /* Internal definition */ };
/*
* The return value of ic_74hc595_change_inputs() returns an encoded form of the
* output pins. You can use ic_74hc595_decodeOutputValue() on this returned value
* to decode individual pins.
*/
void ic_74hc595_power_up(ic_74hc595* ic);
int ic_74hc595_change_inputs(ic_74hc595* ic,
PinState SH_CP, PinState ST_CP,
PinState OE, PinState MR, PinState DS);
PinState ic_74hc595_decodeOutputValue(int QSlots, OutputPinID pin);https://codereview.stackexchange.com/questions/7638
复制相似问题