| 
              #include <stm32f10x.h>
 #define _BV(n) (1 << (n))
 #define CS_0 (GPIOA->BRR = GPIO_BRR_BR3)
 #define CS_1 (GPIOA->BSRR = GPIO_BSRR_BS3)
 #define SK_0 (GPIOA->BRR = GPIO_BRR_BR5)
 #define SK_1 (GPIOA->BSRR = GPIO_BSRR_BS5)
 #define DI_0 (GPIOA->BRR = GPIO_BRR_BR7)
 #define DI_1 (GPIOA->BSRR = GPIO_BSRR_BS7)
 #define DO ((GPIOA->IDR & GPIO_IDR_IDR6) != 0)
 
 uint16_t num = 0;
 uint8_t nid = 0;
 const uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
 
 void delay(void)
 {
 uint16_t i;
 for (i = 0; i < 20000; i++);
 }
 
 void delay_short(void)
 {
 uint16_t i;
 for (i = 0; i < 300; i++);
 }
 
 void ser_in(uint8_t data)
 {
 uint8_t i;
 for (i = 0; i < 8; i++)
 {
 GPIOB->BRR = GPIO_BRR_BR9; // SCLK=>PB9
 if (data & 0x80)
 GPIOB->BSRR = GPIO_BSRR_BS7; // DIO=>PB7
 else
 GPIOB->BRR = GPIO_BRR_BR7;
 data <<= 1;
 GPIOB->BSRR = GPIO_BSRR_BS9;
 }
 }
 
 void par_out(void)
 {
 GPIOB->BRR = GPIO_BRR_BR8; // RCLK=>PB8
 GPIOB->BSRR = GPIO_BSRR_BS8;
 }
 
 void seg_scan(void)
 {
 uint8_t i;
 uint32_t n = num;
 for (i = 0; i <= 4; i++)
 {
 ser_in(seg8[n % 10]);
 ser_in(_BV(i));
 par_out();
 delay();
 n /= 10;
 }
 
 n = nid;
 for (i = 6; i <= 7; i++)
 {
 ser_in(seg8[n % 10]);
 ser_in(_BV(i));
 par_out();
 delay();
 n /= 10;
 }
 }
 
 void _93C46_WriteOP(uint8_t op)
 {
 // 初态
 CS_0;
 SK_0;
 
 // 开始位
 DI_1;
 CS_1;
 delay_short(); // tCSS>=0.5us
 SK_1;
 delay_short(); // tSKH>=0.25us
 SK_0;
 //delay_short(); // tSKL>=0.25us, 由于下面已经有一句延时了, 所以这句可以不要
 
 // OP位
 if ((op & 2) == 0) // 操作码第一位
 DI_0;
 delay_short(); // 数据在下降沿至少要保持tDIS>=0.1us
 SK_1;
 delay_short(); // 数据在上升沿至少要保持tDIH>=0.1us的时间
 SK_0;
 if (op & 1) // 改变数据, 发送操作码第二位
 DI_1;
 else
 DI_0;
 delay_short(); // tDIS, tSKL
 
 SK_1;
 delay_short(); // tDIH, tSKH
 SK_0;
 delay_short(); // tSKL
 }
 
 void _93C46_WriteAddress(uint8_t addr)
 {
 uint8_t i;
 for (i = 0; i < 6; i++)
 {
 if (addr & 0x20)
 DI_1;
 else
 DI_0;
 delay_short(); // tDIS, tSKL
 SK_1;
 delay_short(); // tSKH
 SK_0;
 addr <<= 1;
 }
 delay_short(); // tSKL
 DI_0;
 }
 
 uint16_t _93C46_ReadWord(void)
 {
 uint8_t i;
 uint16_t data = 0;
 for (i = 0; i < 16; i++)
 {
 // SK上升沿出现后tPD<=0.25us,才出现本位要读的数据
 SK_1;
 delay_short();
 data <<= 1;
 if (DO)
 data |= 1;
 SK_0;
 delay_short();
 }
 return data;
 }
 
 uint16_t _93C46_Read(uint8_t addr)
 {
 uint16_t data;
 _93C46_WriteOP(2);
 _93C46_WriteAddress(addr);
 data = _93C46_ReadWord();
 CS_0;
 return data;
 }
 
 void _93C46_WriteWord(uint16_t dat)
 {
 uint8_t i;
 for (i = 0; i < 16; i++)
 {
 if (dat & 0x8000)
 DI_1;
 else
 DI_0;
 delay_short(); // tDIS, tSKL
 SK_1;
 delay_short(); // tSKH
 SK_0;
 dat <<= 1;
 }
 delay_short(); // tSKL
 DI_0;
 }
 
 // 等待操作完毕
 void _93C46_Wait(void)
 {
 CS_0;
 CS_1;
 delay_short(); // tSV<=250ns
 while (!DO);
 CS_0;
 }
 
 // 允许/禁止擦写
 void _93C46_EnableWrite(uint8_t enabled)
 {
 _93C46_WriteOP(0);
 _93C46_WriteAddress((enabled) ? 0x30 : 0x00);
 CS_0;
 }
 
 // 写入单个存储单元
 void _93C46_Write(uint8_t addr, uint16_t dat)
 {
 _93C46_WriteOP(1);
 _93C46_WriteAddress(addr);
 _93C46_WriteWord(dat);
 _93C46_Wait();
 }
 
 // 擦除单个存储单元
 void _93C46_Erase(uint8_t addr)
 {
 _93C46_WriteOP(3);
 _93C46_WriteAddress(addr);
 _93C46_Wait();
 }
 
 // 擦除所有存储单元
 // 经测试,该命令可以在3.2V的电压下完成
 // 本人使用的是ST公司的93C46芯片,和STM32单片机是同一家公司生产的
 void _93C46_EraseAll(void)
 {
 _93C46_WriteOP(0);
 _93C46_WriteAddress(0x20);
 _93C46_Wait();
 }
 
 // 将所有的存储单元设为指定值
 // 同样也可以在3.2V的电压下完成
 void _93C46_WriteAll(uint16_t dat)
 {
 _93C46_WriteOP(0);
 _93C46_WriteAddress(0x10);
 _93C46_WriteWord(dat);
 _93C46_Wait();
 }
 
 int main(void)
 {
 uint8_t i;
 
 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
 GPIOA->CRL = 0x38303000;
 GPIOA->BSRR = GPIO_BSRR_BS6;
 GPIOB->CRH = 0x00000033;
 GPIOB->CRL = 0x30000000;
 
 /*
 _93C46_EnableWrite(1);
 for (i = 0; i < 64; i++)
 _93C46_Write(i, 40000 + i * 100 + i);
 _93C46_EnableWrite(0);
 */
 
 while (1)
 {
 num = _93C46_Read(nid);
 for (i = 0; i < 50; i++)
 seg_scan();
 
 nid++;
 if (nid > 63)
 nid = 0;
 }
 }
 
 |