算是填了最先挖的 VFD 坑 https://www.cnblogs.com/katachi/p/8324202.html
最近 pcb 厂家神仙打架, 为 PCB 普及做出了巨大贡献, 到这事儿发生我也就开了两三次板, 都赶上这个时间了, 不开白不开!
不说了, 上图!
sch:
pcb:
方案和之前的除了驱动电路都一样, 以前那个自己绕变压器的方案发热量太大了. 但是那组电路参数照样可以用的.
这次 pcb 除了几处纰漏, 灯丝高压应该直接改为负高压, 还有就是 pmos 不知道为啥错位了, 可能是拼版的时候不小心移动了.
至于程序方面大部分直接用, 由于不想改显示驱动, grid 和 digit 还是将错就错, 加一步 call transcode() 罢了.
改动比较大的就是 ds3231 的驱动, 原来使用 stm8 硬件 iic. 这次一开始调试的时候总是卡在忙, 以前也有这个现象, 一怒之下直接改成软件 iic.
把以前的驱动拿过来改改方法就成了.
iic.h
- #ifndef __MYIICDS3231_H
- #define __MYIICDS3231_H
- #include "stm8s.h"
- #include "delay.h"
- #include "iostm8s103f3.h" //inc the .h to use bit control
- //transplanted to dsd3231
- //modyfied:
- //1.only leave 8 bit to work
- //2.change the related macro definition
- //3.use newer stm8s_i2c.h
- //By katachi time:2018-1-20
- //new added 19-3-14:
- //DS3231IIC_BufferRead()
- //new modify 19-4-12 fot stc15
- //new modify 4-2x for stm8 software iic
- ////IO 方向设置
- //#define DS3231IIC_SDA_IN() {GPIOB->CRL&=0XFFFFF0FF;GPIOB->CRL|=8<<8;}
- //#define DS3231IIC_SDA_OUT() {GPIOB->CRL&=0XFFFFF0FF;GPIOB->CRL|=3<<8;}
- ////IO 操作函数
- //#define DS3231IIC_SCL PBout(3) //SCL
- //#define DS3231IIC_SDA PBout(2) //SDA
- //#define DS3231IIC_READ_SDA PBin(2) // 输入 SDA
- ////IO 方向设置
- #define DS3231IIC_SDA_IN() {GPIO_Init(GPIOB,(GPIO_PIN_5),GPIO_MODE_IN_PU_NO_IT);}
- #define DS3231IIC_SDA_OUT() {GPIO_Init(GPIOB,(GPIO_PIN_5),GPIO_MODE_OUT_PP_HIGH_FAST);}
- ////IO 操作函数
- #define DS3231IIC_SCL PB_ODR_ODR4 //SCL
- #define DS3231IIC_SDA PB_ODR_ODR5 //SDA
- #define DS3231IIC_READ_SDA PB_IDR_IDR5 // 输入 SDA
- //IIC 所有操作函数
- void DS3231IIC_Init(void); // 初始化 IIC 的 IO 口
- void DS3231IIC_Start(void); // 发送 IIC 开始信号
- void DS3231IIC_Stop(void); // 发送 IIC 停止信号
- void DS3231IIC_Send_Byte(u8 txd); //IIC 发送一个字节
- u8 DS3231IIC_Read_Byte(unsigned char ack);//IIC 读取一个字节
- u8 DS3231IIC_Wait_Ack(void); //IIC 等待 ACK 信号
- void DS3231IIC_Ack(void); //IIC 发送 ACK 信号
- void DS3231IIC_NAck(void); //IIC 不发送 ACK 信号
- void DS3231IIC_Write_One_Byte(u8 addr,u8 dat);
- u8 DS3231IIC_Read_One_Byte(u8 addr);
- void DS3231IIC_BufferRead(u8 *buffer,u8 startAddr,u8 bufferLen);
- void DS3231IIC_ReverseDirBufferRead(u8 *buffer,u8 startAddr,u8 bufferLen);
- #endif
- View Code
- iic.c
- #include "myiicForDs3231.h"
- #include "ds3231.h" //only for iic addr
- #include "delay.h"
- // 初始化 IIC
- void DS3231IIC_Init(void)
- {
- //// GPIO_InitTypeDef GPIO_InitStructure;
- //// RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE );
- //// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //remapping pb4,3 from jtag to general gpio
- ////
- //// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
- //// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; // 推挽输出
- //// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- //// GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_Init(GPIOB,(GPIO_PIN_5|GPIO_PIN_4),GPIO_MODE_OUT_PP_HIGH_FAST); //scl pb4;sda pb5
- DS3231IIC_SCL=1;
- DS3231IIC_SDA=1;
- delay_ms(50);
- }
- // 产生 IIC 起始信号
- void DS3231IIC_Start(void)
- {
- DS3231IIC_SDA_OUT(); //sda 线输出
- DS3231IIC_SDA=1;
- DS3231IIC_SCL=1;
- delay_us(4);
- DS3231IIC_SDA=0;//START:when CLK is high,DATA change form high to low
- delay_us(4);
- DS3231IIC_SCL=0;// 钳住 I2C 总线, 准备发送或接收数据
- }
- // 产生 IIC 停止信号
- void DS3231IIC_Stop(void)
- {
- DS3231IIC_SDA_OUT();//sda 线输出
- DS3231IIC_SCL=0;
- DS3231IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
- delay_us(4);
- DS3231IIC_SCL=1;
- DS3231IIC_SDA=1;// 发送 I2C 总线结束信号
- delay_us(4);
- }
- // 等待应答信号到来
- // 返回值: 1, 接收应答失败
- // 0, 接收应答成功
- u8 DS3231IIC_Wait_Ack(void)
- {
- u8 ucErrTime=0;
- DS3231IIC_SDA_IN(); //SDA 设置为输入
- DS3231IIC_SDA=1;delay_us(1);
- DS3231IIC_SCL=1;delay_us(1);
- while(DS3231IIC_READ_SDA)
- {
- ucErrTime++;
- if(ucErrTime>250)
- {
- DS3231IIC_Stop();
- return 1;
- }
- }
- DS3231IIC_SCL=0;// 时钟输出 0
- return 0;
- }
- // 产生 ACK 应答
- void DS3231IIC_Ack(void)
- {
- DS3231IIC_SCL=0;
- DS3231IIC_SDA_OUT();
- DS3231IIC_SDA=0;
- delay_us(2);
- DS3231IIC_SCL=1;
- delay_us(2);
- DS3231IIC_SCL=0;
- }
- // 不产生 ACK 应答
- void DS3231IIC_NAck(void)
- {
- DS3231IIC_SCL=0;
- DS3231IIC_SDA_OUT();
- DS3231IIC_SDA=1;
- delay_us(2);
- DS3231IIC_SCL=1;
- delay_us(2);
- DS3231IIC_SCL=0;
- }
- //IIC 发送一个字节
- // 返回从机有无应答
- //1, 有应答
- //0, 无应答
- void DS3231IIC_Send_Byte(u8 txd)
- {
- u8 t;
- DS3231IIC_SDA_OUT();
- DS3231IIC_SCL=0;// 拉低时钟开始数据传输
- for(t=0;t<8;t++)
- {
- DS3231IIC_SDA=(txd&0x80)>>7;
- txd<<=1;
- delay_us(2); // 对 TEA5767 这三个延时都是必须的
- DS3231IIC_SCL=1;
- delay_us(2);
- DS3231IIC_SCL=0;
- delay_us(2);
- }
- }
- // 读 1 个字节, ack=1 时, 发送 ACK,ack=0, 发送 nACK
- u8 DS3231IIC_Read_Byte(unsigned char ack)
- {
- unsigned char i,receive=0;
- DS3231IIC_SDA_IN();//SDA 设置为输入
- for(i=0;i<8;i++ )
- {
- DS3231IIC_SCL=0;
- delay_us(2);
- DS3231IIC_SCL=1;
- receive<<=1;
- if(DS3231IIC_READ_SDA)receive++;
- delay_us(1);
- }
- if (!ack)
- DS3231IIC_NAck();// 发送 nACK
- else
- DS3231IIC_Ack(); // 发送 ACK
- return receive;
- }
- void DS3231IIC_Write_One_Byte(u8 addr,u8 dat){
- DS3231IIC_Start();
- DS3231IIC_Send_Byte(DS3231_WriteAddress);
- DS3231IIC_Wait_Ack();
- DS3231IIC_Send_Byte(addr);
- DS3231IIC_Wait_Ack();
- DS3231IIC_Send_Byte(dat);
- DS3231IIC_Wait_Ack();
- DS3231IIC_Stop();
- }
- u8 DS3231IIC_Read_One_Byte(u8 addr){
- u8 tmp;
- DS3231IIC_Start();
- DS3231IIC_Send_Byte(DS3231_WriteAddress);
- DS3231IIC_Wait_Ack();
- DS3231IIC_Send_Byte(addr);
- DS3231IIC_Wait_Ack();
- DS3231IIC_Start();
- DS3231IIC_Send_Byte(DS3231_ReadAddress);
- DS3231IIC_Wait_Ack();
- tmp = DS3231IIC_Read_Byte(0);
- DS3231IIC_Stop();
- return tmp;
- }
- void DS3231IIC_BufferRead(u8 *buffer, u8 startAddr, u8 bufferLen)
- {
- u8 t,add=startAddr;
- for(t=0;t<bufferLen;t++)
- {
- *buffer=DS3231IIC_Read_One_Byte(add++);
- buffer++;
- }
- }
- void DS3231IIC_ReverseDirBufferRead(u8 *buffer, u8 startAddr, u8 bufferLen)
- {
- u8 t,add=startAddr;
- for(t=0;t<bufferLen;t++)
- {
- *buffer=DS3231IIC_Read_One_Byte(add--);
- buffer++;
- }
- }
- View Code
- main.c
- #include "stm8s.h"
- #include "stm8s_clk.h"
- #include "intrinsics.h"
- #include "stm8s_uart1.h"
- #include "uart.h"
- #include "sysclock.h"
- #include "delay.h"
- #include "stm8s_i2c.h"
- #include "pt6311.h"
- #include "ds3231.h"
- #include "myiicForDs3231.h"
- #include "stm8s_tim1.h"
- void Tim1_Init(void)
- {
- TIM1_TimeBaseInit(15,TIM1_COUNTERMODE_UP,10000,0);//10ms
- TIM1_ARRPreloadConfig(ENABLE);
- TIM1_ITConfig(TIM1_IT_UPDATE , ENABLE);
- TIM1_Cmd(ENABLE);
- }
- u8 t_flag,tempOrDate_flag,cnt_5s;
- int main(void)
- {
- u8 dat[6];
- //use this fuction to choose a clock
- SystemClock_Init(HSI_Clock); //hsi
- //CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
- /*!<Set High speed internal clock */
- Uart_Init();
- delay_init(16);//@delay.c
- DS3231IIC_Init();
- delay_ms(100);
- //ModifyTime(4,30,2,0,16,0);//set a default time to avoid error!!!
- __enable_interrupt();//enable it
- printf("now system start!!!\r\n");
- Init_PT6311();//initialize pt6311
- //DeDisplayVfd();//dedisplay vfd screen
- Tim1_Init();
- while (1)
- {
- if (t_flag){
- t_flag=0;
- if (++cnt_5s>=10)
- {
- cnt_5s=0;
- if (++tempOrDate_flag>=3)tempOrDate_flag=0;//0->date 1->temperature 2->week
- if (tempOrDate_flag==0){
- get_date(dat);
- dspseg[1]=dat[0]/10;
- dspseg[2]=dat[0]%10;//mon
- dspseg[3]=(dat[1]/10);
- dspseg[4]=dat[1]%10;//day
- dspseg[5]=dat[2];//wk
- dspseg[12]=dat[2];//dspseg[12] 0-3:wk 4-7:sec
- }
- else if (tempOrDate_flag==1){
- get_Temperature(dat);
- dspseg[0]=dat[0]/3;
- dspseg[1]='t';
- dspseg[2]=36|COLON;
- dspseg[3]=(dat[0]/10);
- dspseg[4]=dat[0]%10;
- dspseg[5]='c';
- }
- else{
- get_date(dat);
- WeekDisplay(dat[2]);
- dspseg[4]=36;
- dspseg[5]=36;//clr
- }
- }
- get_time(&dat[3]);//get h m s
- dspseg[6]=dat[3]/10; //h
- dspseg[7]=dat[3]%10|COLON;
- dspseg[8]=dat[4]/10; //min
- dspseg[9]=(dat[4]%10)|COLON;
- dspseg[10]=dat[5]/10;
- dspseg[11]=(dat[5]%10);//sec
- dspseg[12]=(dspseg[12]&0x0f)|(dspseg[11]<<4);//dspseg[12] 0-3:wk 4-7:sec//ui moving
- if ((dat[3]<=23) && (dat[3]>=5)){
- OpenStrobe_PT6311();
- WriteByte_PT6311(CMD_DisplaySetting|0x08|4);
- STB=1;
- }else
- {
- OpenStrobe_PT6311();
- WriteByte_PT6311(CMD_DisplaySetting|0x08|2);
- STB=1;
- }
- DisplayVfd();//reflash vfd
- }
- if(UART_RX_NUM&0x80)//uart catch
- {
- CMD_Compare();
- }
- }
- }
- //#ifdef USE_FULL_ASSERT //@stm8s_conf.h commented the macro
- //
- ///**
- //* @brief Reports the name of the source file and the source line number
- //* where the assert_param error has occurred.
- //* @param file: pointer to the source file name
- //* @param line: assert_param error line source number
- //* @retval : None
- //*/
- //void assert_failed(u8* file, u32 line)
- //{
- // /* User can add his own implementation to report the file name and line number,
- // ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- //
- // /* Infinite loop */
- // while (1)
- // {
- // }
- //}
- //#endif
- View Code
- uart.c
- #include "uart.h"
- #include "stm8s.h"
- #include "stm8s_clk.h"
- #include <stdarg.h>
- #include "string.h"
- #include "pt6311.h"
- #include "ds3231.h"
- /* ********************************************
- UART1 configured as follow:
- - BaudRate = 115200 baud
- - Word Length = 8 Bits
- - One Stop Bit
- - No parity
- - Receive and transmit enabled
- - Receive interrupt
- - UART1 Clock disabled
- *********************************************/
- void DataDel(u8 *str,u8 len)
- {
- u8 i;
- for (i=0;i<len-8;i++)
- str[i]=str[i+8];
- }
- void CMD_Compare(void) //
- {
- u8 tmp[9]={0};
- u8 i,len;
- len=UART_RX_NUM&0x3f;//get the length
- printf("\r\nWhat you have in put is:\r\n");
- UART1_SendString(RxBuffer,len);
- printf("\r\n");
- //get cmd
- // for (i=0;i<8;i++)
- // tmp[i]=RxBuffer[i];
- strncpy(tmp,(const char*)RxBuffer,8);
- //cmd explaine
- if (strcmp("cmd_time",(const char*)tmp)==0)
- {
- printf("now modify time!\r\n");
- DataDel(RxBuffer,len);//del cmd to get data
- //combine the data && transport from ascii to value
- //ModifyTime(4,12,5,11,21,0);// 4-12 w5 tm11-21-00
- ModifyTime((RxBuffer[0]-'0')*10 + RxBuffer[1]-'0', //month
- (RxBuffer[2]-'0')*10 + RxBuffer[3]-'0',//day
- (RxBuffer[4]-'0'), //week
- (RxBuffer[5]-'0')*10 + RxBuffer[6]-'0',//hr
- (RxBuffer[7]-'0')*10 + RxBuffer[8]-'0',//min
- (RxBuffer[9]-'0')*10 + RxBuffer[10]-'0');//sec
- }
- else if (strcmp("cmd_ala1",(const char*)tmp)==0)
- {
- }
- else if(strcmp("cmd_ligh",(const char*)tmp)==0)
- {
- printf("now modify light!\r\n");
- DataDel(RxBuffer,len);//del cmd to get data
- RxBuffer[0]-='0';
- printf("to level :%d", RxBuffer[0]);
- OpenStrobe_PT6311();
- WriteByte_PT6311(CMD_DisplaySetting|0x08|RxBuffer[0]);//on 14/16
- STB=1;
- }
- //clr
- for (i=0;i<len;i++)
- RxBuffer[i]=0;
- UART_RX_NUM=0;//clr
- }
- void Uart_Init(void)
- {
- UART1_DeInit();
- UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, 76 UART1_PARITY_NO , UART1_SYNCMODE_CLOCK_DISABLE , UART1_MODE_TXRX_ENABLE);
- UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE );
- UART1_Cmd(ENABLE );
- }
- void UART1_SendByte(u8 data)
- {
- UART1_SendData8((unsigned char)data);
- /* Loop until the end of transmission */
- while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
- }
- void UART1_SendString(u8* Data,u16 len)
- {
- u16 i=0;
- for(;i<len;i++)
- UART1_SendByte(Data[i]);
- }
- u8 UART1_ReceiveByte(void)
- {
- u8 USART1_RX_BUF;
- while (UART1_GetFlagStatus(UART1_FLAG_RXNE) == RESET);
- USART1_RX_BUF=UART1_ReceiveData8();
- return USART1_RX_BUF;
- }
- /*
- * 函数名: fputc
- * 描述 : 重定向 c 库函数 printf 到 USART1
- * 输入 : 无
- * 输出 : 无
- * 调用 : 由 printf 调用
- */
- int fputc(int ch, FILE *f)
- {
- /* 将 Printf 内容发往串口 */
- UART1_SendData8((unsigned char) ch);
- while (!(UART1->SR & UART1_FLAG_TXE));
- return (ch);
- }
- View Code
主程序流程就是定时器中断产生节拍, 然后去读 3231, 显示, 以及串口命令解析
效果图:
这个屏比较长, pcb 只画了 10cm, 设计时忘记考虑 usb 口了, 短在里面难受!
安鑫那边应该还在卖.
这个月点了 3 个 VFD 屏, 还屯了不少. 中间快递丢了, 重新花 50+RMB 重新买, 都是泪, 哭.
来源: http://www.bubuko.com/infodetail-3044759.html