算是填了最先挖的VFD坑

最近pcb厂家神仙打架,为PCB普及做出了巨大贡献,到这事儿发生我也就开了两三次板,都赶上这个时间了,不开白不开!


不说了,上图!

sch:

pcb:

方案和之前的除了驱动电路都一样,以前那个自己绕变压器的方案发热量太大了。但是那组电路参数照样可以用的。

这次pcb除了几处纰漏,灯丝高压应该直接改为负高压,还有就是pmos不知道为啥错位了,可能是拼版的时候不小心移动了。

至于程序方面大部分直接用,由于不想改显示驱动,grid和digit还是将错就错,加一步call transcode() 罢了。

改动比较大的就是ds3231的驱动,原来使用stm8硬件iic。这次一开始调试的时候总是卡在忙,以前也有这个现象,一怒之下直接改成软件iic。

把以前的驱动拿过来改改方法就成了。

iic.h

  1. #ifndef __MYIICDS3231_H
  2. #define __MYIICDS3231_H
  3. #include "stm8s.h"
  4. #include "delay.h"
  5. #include "iostm8s103f3.h" //inc the .h to use bit control
  6.  
  7. //transplanted to dsd3231
  8. //modyfied:
  9. //1.only leave 8 bit to work
  10. //2.change the related macro definition
  11. //3.use newer stm8s_i2c.h
  12. //By katachi time:2018-1-20
  13. //new added 19-3-14:
  14. //DS3231IIC_BufferRead()
  15. //new modify 19-4-12 fot stc15
  16. //new modify 4-2x for stm8 software iic
  17.  
  18. ////IO方向设置
  19. //#define DS3231IIC_SDA_IN() {GPIOB->CRL&=0XFFFFF0FF;GPIOB->CRL|=8<<8;}
  20. //#define DS3231IIC_SDA_OUT() {GPIOB->CRL&=0XFFFFF0FF;GPIOB->CRL|=3<<8;}
  21.  
  22. ////IO操作函数
  23. //#define DS3231IIC_SCL PBout(3) //SCL
  24. //#define DS3231IIC_SDA PBout(2) //SDA
  25. //#define DS3231IIC_READ_SDA PBin(2) //输入SDA
  26.  
  27. ////IO方向设置
  28. #define DS3231IIC_SDA_IN() {GPIO_Init(GPIOB,(GPIO_PIN_5),GPIO_MODE_IN_PU_NO_IT);}
  29. #define DS3231IIC_SDA_OUT() {GPIO_Init(GPIOB,(GPIO_PIN_5),GPIO_MODE_OUT_PP_HIGH_FAST);}
  30.  
  31. ////IO操作函数
  32. #define DS3231IIC_SCL PB_ODR_ODR4 //SCL
  33. #define DS3231IIC_SDA PB_ODR_ODR5 //SDA
  34. #define DS3231IIC_READ_SDA PB_IDR_IDR5 //输入SDA
  35.  
  36. //IIC所有操作函数
  37. void DS3231IIC_Init(void); //初始化IIC的IO口
  38. void DS3231IIC_Start(void); //发送IIC开始信号
  39. void DS3231IIC_Stop(void); //发送IIC停止信号
  40. void DS3231IIC_Send_Byte(u8 txd); //IIC发送一个字节
  41. u8 DS3231IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
  42. u8 DS3231IIC_Wait_Ack(void); //IIC等待ACK信号
  43. void DS3231IIC_Ack(void); //IIC发送ACK信号
  44. void DS3231IIC_NAck(void); //IIC不发送ACK信号
  45.  
  46. void DS3231IIC_Write_One_Byte(u8 addr,u8 dat);
  47. u8 DS3231IIC_Read_One_Byte(u8 addr);
  48. void DS3231IIC_BufferRead(u8 *buffer,u8 startAddr,u8 bufferLen);
  49. void DS3231IIC_ReverseDirBufferRead(u8 *buffer,u8 startAddr,u8 bufferLen);
  50. #endif

iic.c

  1. #include "myiicForDs3231.h"
  2. #include "ds3231.h" //only for iic addr
  3. #include "delay.h"
  4.  
  5. //初始化IIC
  6. void DS3231IIC_Init(void)
  7. {
  8. //// GPIO_InitTypeDef GPIO_InitStructure;
  9. //// RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE );
  10. //// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //remapping pb4,3 from jtag to general gpio
  11. ////
  12. //// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
  13. //// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
  14. //// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15. //// GPIO_Init(GPIOB, &GPIO_InitStructure);
  16.  
  17. GPIO_Init(GPIOB,(GPIO_PIN_5|GPIO_PIN_4),GPIO_MODE_OUT_PP_HIGH_FAST); //scl pb4;sda pb5
  18. DS3231IIC_SCL=;
  19. DS3231IIC_SDA=;
  20. delay_ms();
  21. }
  22. //产生IIC起始信号
  23. void DS3231IIC_Start(void)
  24. {
  25. DS3231IIC_SDA_OUT(); //sda线输出
  26. DS3231IIC_SDA=;
  27. DS3231IIC_SCL=;
  28. delay_us();
  29. DS3231IIC_SDA=;//START:when CLK is high,DATA change form high to low
  30. delay_us();
  31. DS3231IIC_SCL=;//钳住I2C总线,准备发送或接收数据
  32. }
  33. //产生IIC停止信号
  34. void DS3231IIC_Stop(void)
  35. {
  36. DS3231IIC_SDA_OUT();//sda线输出
  37. DS3231IIC_SCL=;
  38. DS3231IIC_SDA=;//STOP:when CLK is high DATA change form low to high
  39. delay_us();
  40. DS3231IIC_SCL=;
  41. DS3231IIC_SDA=;//发送I2C总线结束信号
  42. delay_us();
  43. }
  44. //等待应答信号到来
  45. //返回值:1,接收应答失败
  46. // 0,接收应答成功
  47. u8 DS3231IIC_Wait_Ack(void)
  48. {
  49. u8 ucErrTime=;
  50. DS3231IIC_SDA_IN(); //SDA设置为输入
  51. DS3231IIC_SDA=;delay_us();
  52. DS3231IIC_SCL=;delay_us();
  53. while(DS3231IIC_READ_SDA)
  54. {
  55. ucErrTime++;
  56. if(ucErrTime>)
  57. {
  58. DS3231IIC_Stop();
  59. return ;
  60. }
  61. }
  62. DS3231IIC_SCL=;//时钟输出0
  63. return ;
  64. }
  65. //产生ACK应答
  66. void DS3231IIC_Ack(void)
  67. {
  68. DS3231IIC_SCL=;
  69. DS3231IIC_SDA_OUT();
  70. DS3231IIC_SDA=;
  71. delay_us();
  72. DS3231IIC_SCL=;
  73. delay_us();
  74. DS3231IIC_SCL=;
  75. }
  76. //不产生ACK应答
  77. void DS3231IIC_NAck(void)
  78. {
  79. DS3231IIC_SCL=;
  80. DS3231IIC_SDA_OUT();
  81. DS3231IIC_SDA=;
  82. delay_us();
  83. DS3231IIC_SCL=;
  84. delay_us();
  85. DS3231IIC_SCL=;
  86. }
  87. //IIC发送一个字节
  88. //返回从机有无应答
  89. //1,有应答
  90. //0,无应答
  91. void DS3231IIC_Send_Byte(u8 txd)
  92. {
  93. u8 t;
  94. DS3231IIC_SDA_OUT();
  95. DS3231IIC_SCL=;//拉低时钟开始数据传输
  96. for(t=;t<;t++)
  97. {
  98. DS3231IIC_SDA=(txd&0x80)>>;
  99. txd<<=;
  100. delay_us(); //对TEA5767这三个延时都是必须的
  101. DS3231IIC_SCL=;
  102. delay_us();
  103. DS3231IIC_SCL=;
  104. delay_us();
  105. }
  106. }
  107. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  108. u8 DS3231IIC_Read_Byte(unsigned char ack)
  109. {
  110. unsigned char i,receive=;
  111. DS3231IIC_SDA_IN();//SDA设置为输入
  112. for(i=;i<;i++ )
  113. {
  114. DS3231IIC_SCL=;
  115. delay_us();
  116. DS3231IIC_SCL=;
  117. receive<<=;
  118. if(DS3231IIC_READ_SDA)receive++;
  119. delay_us();
  120. }
  121. if (!ack)
  122. DS3231IIC_NAck();//发送nACK
  123. else
  124. DS3231IIC_Ack(); //发送ACK
  125. return receive;
  126. }
  127. void DS3231IIC_Write_One_Byte(u8 addr,u8 dat){
  128. DS3231IIC_Start();
  129. DS3231IIC_Send_Byte(DS3231_WriteAddress);
  130. DS3231IIC_Wait_Ack();
  131. DS3231IIC_Send_Byte(addr);
  132. DS3231IIC_Wait_Ack();
  133. DS3231IIC_Send_Byte(dat);
  134. DS3231IIC_Wait_Ack();
  135. DS3231IIC_Stop();
  136. }
  137. u8 DS3231IIC_Read_One_Byte(u8 addr){
  138. u8 tmp;
  139.  
  140. DS3231IIC_Start();
  141. DS3231IIC_Send_Byte(DS3231_WriteAddress);
  142. DS3231IIC_Wait_Ack();
  143. DS3231IIC_Send_Byte(addr);
  144. DS3231IIC_Wait_Ack();
  145.  
  146. DS3231IIC_Start();
  147. DS3231IIC_Send_Byte(DS3231_ReadAddress);
  148. DS3231IIC_Wait_Ack();
  149. tmp = DS3231IIC_Read_Byte();
  150. DS3231IIC_Stop();
  151.  
  152. return tmp;
  153. }
  154. void DS3231IIC_BufferRead(u8 *buffer, u8 startAddr, u8 bufferLen)
  155. {
  156. u8 t,add=startAddr;
  157.  
  158. for(t=;t<bufferLen;t++)
  159. {
  160. *buffer=DS3231IIC_Read_One_Byte(add++);
  161. buffer++;
  162. }
  163. }
  164. void DS3231IIC_ReverseDirBufferRead(u8 *buffer, u8 startAddr, u8 bufferLen)
  165. {
  166. u8 t,add=startAddr;
  167.  
  168. for(t=;t<bufferLen;t++)
  169. {
  170. *buffer=DS3231IIC_Read_One_Byte(add--);
  171. buffer++;
  172. }
  173. }

main.c

  1. #include "stm8s.h"
  2. #include "stm8s_clk.h"
  3. #include "intrinsics.h"
  4. #include "stm8s_uart1.h"
  5. #include "uart.h"
  6. #include "sysclock.h"
  7. #include "delay.h"
  8. #include "stm8s_i2c.h"
  9. #include "pt6311.h"
  10. #include "ds3231.h"
  11. #include "myiicForDs3231.h"
  12. #include "stm8s_tim1.h"
  13.  
  14. void Tim1_Init(void)
  15. {
  16. TIM1_TimeBaseInit(,TIM1_COUNTERMODE_UP,,);//10ms
  17. TIM1_ARRPreloadConfig(ENABLE);
  18. TIM1_ITConfig(TIM1_IT_UPDATE , ENABLE);
  19. TIM1_Cmd(ENABLE);
  20. }
  21.  
  22. u8 t_flag,tempOrDate_flag,cnt_5s;
  23.  
  24. int main(void)
  25. {
  26. u8 dat[];
  27. //use this fuction to choose a clock
  28. SystemClock_Init(HSI_Clock); //hsi
  29.  
  30. //CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
  31.  
  32. /*!<Set High speed internal clock */
  33. Uart_Init();
  34. delay_init();//@delay.c
  35.  
  36. DS3231IIC_Init();
  37. delay_ms();
  38. //ModifyTime(4,30,2,0,16,0);//set a default time to avoid error!!!
  39. __enable_interrupt();//enable it
  40. printf("now system start!!!\r\n");
  41. Init_PT6311();//initialize pt6311
  42. //DeDisplayVfd();//dedisplay vfd screen
  43. Tim1_Init();
  44. while ()
  45. {
  46. if (t_flag){
  47. t_flag=;
  48. if (++cnt_5s>=)
  49. {
  50. cnt_5s=;
  51. if (++tempOrDate_flag>=)tempOrDate_flag=;//0->date 1->temperature 2->week
  52.  
  53. if (tempOrDate_flag==){
  54. get_date(dat);
  55. dspseg[]=dat[]/;
  56. dspseg[]=dat[]%;//mon
  57.  
  58. dspseg[]=(dat[]/);
  59. dspseg[]=dat[]%;//day
  60.  
  61. dspseg[]=dat[];//wk
  62. dspseg[]=dat[];//dspseg[12] 0-3:wk 4-7:sec
  63. }
  64. else if (tempOrDate_flag==){
  65. get_Temperature(dat);
  66. dspseg[]=dat[]/;
  67. dspseg[]='t';
  68. dspseg[]=|COLON;
  69.  
  70. dspseg[]=(dat[]/);
  71. dspseg[]=dat[]%;
  72. dspseg[]='c';
  73. }
  74. else{
  75. get_date(dat);
  76. WeekDisplay(dat[]);
  77. dspseg[]=;
  78. dspseg[]=;//clr
  79. }
  80. }
  81. get_time(&dat[]);//get h m s
  82. dspseg[]=dat[]/; //h
  83. dspseg[]=dat[]%|COLON;
  84.  
  85. dspseg[]=dat[]/; //min
  86. dspseg[]=(dat[]%)|COLON;
  87.  
  88. dspseg[]=dat[]/;
  89. dspseg[]=(dat[]%);//sec
  90. dspseg[]=(dspseg[]&0x0f)|(dspseg[]<<);//dspseg[12] 0-3:wk 4-7:sec//ui moving
  91. if ((dat[]<=) && (dat[]>=)){
  92. OpenStrobe_PT6311();
  93. WriteByte_PT6311(CMD_DisplaySetting|0x08|);
  94. STB=;
  95. }else
  96. {
  97. OpenStrobe_PT6311();
  98. WriteByte_PT6311(CMD_DisplaySetting|0x08|);
  99. STB=;
  100. }
  101. DisplayVfd();//reflash vfd
  102. }
  103. if(UART_RX_NUM&0x80)//uart catch
  104. {
  105. CMD_Compare();
  106. }
  107. }
  108. }
  109.  
  110. //#ifdef USE_FULL_ASSERT //@stm8s_conf.h commented the macro
  111. //
  112. ///**
  113. // * @brief Reports the name of the source file and the source line number
  114. // * where the assert_param error has occurred.
  115. // * @param file: pointer to the source file name
  116. // * @param line: assert_param error line source number
  117. // * @retval : None
  118. // */
  119. //void assert_failed(u8* file, u32 line)
  120. //{
  121. // /* User can add his own implementation to report the file name and line number,
  122. // ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  123. //
  124. // /* Infinite loop */
  125. // while (1)
  126. // {
  127. // }
  128. //}
  129. //#endif

uart.c

  1. #include "uart.h"
  2. #include "stm8s.h"
  3. #include "stm8s_clk.h"
  4. #include <stdarg.h>
  5. #include "string.h"
  6. #include "pt6311.h"
  7. #include "ds3231.h"
  8.  
  9. /* ********************************************
  10. UART1 configured as follow:
  11. - BaudRate = 115200 baud
  12. - Word Length = 8 Bits
  13. - One Stop Bit
  14. - No parity
  15. - Receive and transmit enabled
  16. - Receive interrupt
  17. - UART1 Clock disabled
  18. *********************************************/
  19. void DataDel(u8 *str,u8 len)
  20. {
  21. u8 i;
  22. for (i=;i<len-;i++)
  23. str[i]=str[i+];
  24. }
  25. void CMD_Compare(void) //
  26. {
  27. u8 tmp[]={};
  28. u8 i,len;
  29.  
  30. len=UART_RX_NUM&0x3f;//get the length
  31. printf("\r\nWhat you have in put is:\r\n");
  32. UART1_SendString(RxBuffer,len);
  33. printf("\r\n");
  34. //get cmd
  35. // for (i=0;i<8;i++)
  36. // tmp[i]=RxBuffer[i];
  37. strncpy(tmp,(const char*)RxBuffer,);
  38. //cmd explaine
  39. if (strcmp("cmd_time",(const char*)tmp)==)
  40. {
  41. printf("now modify time!\r\n");
  42. DataDel(RxBuffer,len);//del cmd to get data
  43. //combine the data && transport from ascii to value
  44. //ModifyTime(4,12,5,11,21,0);// 4-12 w5 tm11-21-00
  45. ModifyTime((RxBuffer[]-'')* + RxBuffer[]-'', //month
  46. (RxBuffer[]-'')* + RxBuffer[]-'',//day
  47. (RxBuffer[]-''), //week
  48. (RxBuffer[]-'')* + RxBuffer[]-'',//hr
  49. (RxBuffer[]-'')* + RxBuffer[]-'',//min
  50. (RxBuffer[]-'')* + RxBuffer[]-'');//sec
  51. }
  52. else if (strcmp("cmd_ala1",(const char*)tmp)==)
  53. {
  54.  
  55. }
  56. else if(strcmp("cmd_ligh",(const char*)tmp)==)
  57. {
  58. printf("now modify light!\r\n");
  59. DataDel(RxBuffer,len);//del cmd to get data
  60. RxBuffer[]-='';
  61.  
  62. printf("to level :%d", RxBuffer[]);
  63. OpenStrobe_PT6311();
  64. WriteByte_PT6311(CMD_DisplaySetting|0x08|RxBuffer[]);//on 14/16
  65. STB=;
  66. }
  67. //clr
  68. for (i=;i<len;i++)
  69. RxBuffer[i]=;
  70. UART_RX_NUM=;//clr
  71. }
  72. void Uart_Init(void)
  73. {
  74. UART1_DeInit();
  75. UART1_Init((u32), UART1_WORDLENGTH_8D, UART1_STOPBITS_1, \
  76. UART1_PARITY_NO , UART1_SYNCMODE_CLOCK_DISABLE , UART1_MODE_TXRX_ENABLE);
  77. UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE );
  78. UART1_Cmd(ENABLE );
  79.  
  80. }
  81.  
  82. void UART1_SendByte(u8 data)
  83. {
  84. UART1_SendData8((unsigned char)data);
  85. /* Loop until the end of transmission */
  86. while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
  87. }
  88.  
  89. void UART1_SendString(u8* Data,u16 len)
  90. {
  91. u16 i=;
  92. for(;i<len;i++)
  93. UART1_SendByte(Data[i]);
  94.  
  95. }
  96.  
  97. u8 UART1_ReceiveByte(void)
  98. {
  99. u8 USART1_RX_BUF;
  100. while (UART1_GetFlagStatus(UART1_FLAG_RXNE) == RESET);
  101. USART1_RX_BUF=UART1_ReceiveData8();
  102. return USART1_RX_BUF;
  103.  
  104. }
  105.  
  106. /*
  107. * 函数名:fputc
  108. * 描述 :重定向c库函数printf到USART1
  109. * 输入 :无
  110. * 输出 :无
  111. * 调用 :由printf调用
  112. */
  113. int fputc(int ch, FILE *f)
  114. {
  115. /* 将Printf内容发往串口 */
  116. UART1_SendData8((unsigned char) ch);
  117. while (!(UART1->SR & UART1_FLAG_TXE));
  118.  
  119. return (ch);
  120. }

主程序流程就是定时器中断产生节拍,然后去读3231,显示,以及串口命令解析

效果图:

这个屏比较长,pcb只画了10cm,设计时忘记考虑usb口了,短在里面难受!

安鑫那边应该还在卖。

这个月点了3个VFD屏,还屯了不少。中间快递丢了,重新花50+RMB重新买,都是泪,哭。

VFD 时钟(VFD Clock with STM8 v2.0)的更多相关文章

  1. 阅读<<HDMI 1.4/2.0 Transmitter Subsystem V2.0>>笔记

    阅读<<HDMI 1.4/2.0 Transmitter Subsystem V2.0>>笔记 1.Subsystem Block Diagram 2.HDMI TX Subs ...

  2. [Android]Android端ORM框架——RapidORM(v2.0)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5626716.html [Android]Android端ORM ...

  3. JuCheap V2.0响应式后台管理系统模板正式发布beta版本

    JuCheap V1.* 查看地址: http://blog.csdn.net/allenwdj/article/details/49155339 经过半年的努力,JuCheap后台通用响应式管理后台 ...

  4. python gettitle v2.0

    #!/usr/bin/env python # coding=utf-8 import threading import requests import Queue import sys import ...

  5. ".NET Compact Framework v2.0 could not be found."

    参考: http://blog.csdn.net/godcyx/article/details/7348431 问题原因: That's a known issue where VS can't di ...

  6. 【JS】heatmap.js v1.0 到 v2.0,详细总结一下:)

    前段时间,项目要开发热力图插件,研究了heatmap.js,打算好好总结一下. 本文主要有以下几部分内容: 部分源码理解 如何迁移到v2.0 v2.0官方文档译文 关于heatmap.js介绍,请看这 ...

  7. 怎样在IDEA中使用JUnit4和JUnitGenerator V2.0自动生成测试模块

     因为项目的需要,所以研究了一下自动生成测试代码.将经验记录下来,总会有用的.我个人认为,好记性不如多做笔记多反思总结. 1.    前提条件 开发环境已正确配置 工程已解决JUnit依赖关系(pom ...

  8. 微信快速开发框架(六)-- 微信快速开发框架(WXPP QuickFramework)V2.0版本上线--源码已更新至github

    4月28日,已增加多媒体上传及下载API,对应MediaUploadRequest和MediaGetRequest ------------------------------------------ ...

  9. 【原创】风讯DotNetCMS V1.0~V2.0 SQL注入漏洞

      文章作者:rebeyond 注:文章首发I.S.T.O信息安全团队,后由原创作者友情提交到乌云-漏洞报告平台.I.S.T.O版权所有,转载需注明作者. 受影响版本:貌似都受影响. 漏洞文件:use ...

随机推荐

  1. art-template 弹出编辑

    <!-- 模板 --> <script id="render-tpl" type="text/html"> <div class= ...

  2. LeetCode 242. 有效的字母异位词(Valid Anagram)

    242. 有效的字母异位词 LeetCode242. Valid Anagram 题目描述 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词. 示例 1: 输入: s ...

  3. 获取可视区域高度赋值给div(解决document.body.clientHeight的返回值为0的问题)

    设置html,body{height:100%} 在使用html5文档类型的时候, 设置了html body的高度100%之后,两个浏览器就都能获取document.body.clientHeight ...

  4. STM32之中断函数

    本文做中断函数的索引,帮助我们找到中断函数名.中断函数参数以及中断服务函数他们的来源,以便我们编程. 1)如果一个工程只有一个中断,则我们可以进行两个步骤就可以了: 使能中断通道 编写中断服务函数 2 ...

  5. php中比较复杂但又常用的字符串函数

    php系统核心库自带的函数中,字符串比数组函数较为简单,但还是有一些较为复杂但又很常用的函数,比如下面的这些函数 explode()函数 用一个字符串来分割另一个字符串,返回结果是一个数组 explo ...

  6. on duplicate key mysql插入更新

    insert into `test` (`job_id`, `user_name`, `total_time`) values ('12345', 'zhangsan', '10') on dupli ...

  7. Golang官方log包详解

    Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use ...

  8. easyExcel用于导入导出

    1.添加依赖: <!-- 现在已经更新到1.1.2-beta5 --> <dependency> <groupId>com.alibaba</groupId& ...

  9. NoSql 使用小结

    NoSql 使用小结 足够的冗余 如果出现要拿某个 id 去查另外的 collection 的情况,说明应该往这个增加所要查询的字段 实在要做关联查询的话,是不是应该考虑关系型的数据库,关系和非关系混 ...

  10. 将网站升级为https并自动续期Https证书。

    Let's Encrypt Let's Encrypt 是一个由Internet Security Research Group (互联网安全研究组)提供的免费,自动化和开放的证书颁发机构. 它秉承着 ...