#include <stm32f10x.h>
#define _BV(n) (1 << (n))
#define SCL_1 GPIOB->BSRR = _BV(6)
#define SCL_0 GPIOB->BRR = _BV(6)
#define SDA ((GPIOB->IDR & _BV(7)) != 0)
#define SDA_1 GPIOB->BSRR = _BV(7)
#define SDA_0 GPIOB->BRR = _BV(7)
#define SDA_R GPIOB->CRL = 0x83000000
#define SDA_W GPIOB->CRL = 0x33000000
uint8_t num = 0;
uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
void delay_short(void)
{
uint8_t i;
for (i = 0; i < 6; i++);
}
void delay(void)
{
uint32_t i;
for (i = 0; i < 20000; i++);
}
void SerIn(uint8_t data)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
GPIOC->BRR = _BV(15);
if (data & 0x80)
GPIOA->BSRR = _BV(0);
else
GPIOA->BRR = _BV(0);
GPIOC->BSRR = _BV(15);
data <<= 1;
}
}
void ParOut(void)
{
GPIOC->BRR = _BV(14);
GPIOC->BSRR = _BV(14);
}
void seg_scan(void)
{
SerIn(seg8[num / 100]);
SerIn(_BV(2));
ParOut();
delay();
SerIn(seg8[num % 100 / 10]);
SerIn(_BV(1));
ParOut();
delay();
SerIn(seg8[num % 10]);
SerIn(_BV(0));
ParOut();
delay();
}
void I2CStart(void)
{
SDA_1;
SCL_1;
delay_short();
SDA_0;
delay_short();
}
void I2CStop(void)
{
SDA_0;
SCL_1;
delay_short();
SDA_1;
// 必须延长足够的时间
delay();
delay();
}
uint8_t I2CAck(void)
{
uint8_t ack;
SDA_1;
SCL_0;
delay_short();
SDA_R; // 这两行不可交换!
SCL_1; //
delay_short();
ack = SDA;
SDA_W;
SCL_0;
return !ack;
}
void I2CSendAck(uint8_t ack)
{
if (ack)
SDA_0;
else
SDA_1;
delay_short();
SCL_1;
delay_short();
SCL_0;
}
uint8_t I2CWrite(uint8_t dat)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
SCL_0;
if (dat & 0x80)
SDA_1;
else
SDA_0;
dat <<= 1;
SCL_1;
delay_short();
}
SCL_0;
return I2CAck();
}
uint8_t I2CRead(void)
{
uint8_t i;
uint8_t dat = 0;
SDA_1;
SDA_R;
for (i = 0; i < 8; i++)
{
SCL_1;
dat <<= 1;
if (SDA)
dat |= 1;
SCL_0;
delay_short();
}
SDA_W;
return dat;
}
void read(void)
{
I2CStart();
I2CWrite(0xa0);
I2CWrite(0x00); // 从0x00处开始连续读三个字节
I2CStart();
I2CWrite(0xa1);
I2CRead();
I2CSendAck(1);
I2CRead();
I2CSendAck(1);
num = I2CRead();
I2CSendAck(0);
I2CStop();
}
void write(void)
{
I2CStart();
I2CWrite(0xa0);
I2CWrite(0x01); // 从0x01处开始连续写两个字节
I2CWrite(36);
I2CWrite(51);
I2CStop();
}
int main(void)
{
RCC->APB2ENR = 0x1c; // 开启PA、PB、PC时钟
GPIOA->CRL = 0x00000003; // PA0设为输出
GPIOB->CRL = 0x33000000; // PB6~7设为推挽50MHz输出
GPIOC->CRH = 0x33000000; // PC14~15设为输出
// 初始化总线
SCL_1;
SDA_1;
write();
read();
while (1)
{
seg_scan(); // 数码管显示051
}
}