| 
            
            
             
              #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;     } }              
                       |