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