Jblog 是一个基于JAVA;适合JAVA初、中级水平编程人员使用、阅读并修改源代码的个人博客系统,不如来丁丁的 Jblog Git OSChina 瞧瞧?

MySQL FEDERATED引擎创建跨库同步表

MySQL FEDERATED引擎创建跨库同步表

该功能类似于Oracle的DBLink,可以跨库、跨服务器查询和关联。首先检查是否支持FEDERATED引擎:

show engines
engine support
PERFORMANCE_SCHEMA YES
MyISAM YES
MRG_MYISAM YES
MEMORY YES
InnoDB DEFAULT
FEDERATED YES
CSV YES
BLACKHOLE YES
ARCHIVE YES

如果提示FEDERATED的SUPPORT为NO,说明MySQL安装了Federated引擎,但是没有启用,此时需要修改mysql.ini | mysql.cnf 文件,在最后添加一行FEDERATED,重启MySQL即可。

如果上述列表压根没有出现FEDERATE条目,说明MySQL服务器版本太低或者安装时不完全,请做好备份重新安装最新的版本。

接下来在需要的库中创建镜像表,表结构需要跟原始表完全一致,示例代码如下

CREATE TABLE `weight`(
    `Id` int(11) NOT NULL AUTO_INCREMENT,
    `weight` float(4,1) DEFAULT '0.0',
    `createat` datetime DEFAULT NULL,
    PRIMARY KEY (`Id`)
) ENGINE=FEDERATED CONNECTION='mysql://username:password@host:port/db_name/table_name'

Sublime中配置Golang开发环境

最近在接触Golang,感觉很棒,等手上这个小项目用Golang搞定后,会出一个Golang的系列博客。

在Sublime中配置Golang开发环境是比较容易的。主要是插件的选择,这里我们选择GoSublime,看中他的函数解析能力,能在大多数情况下将变量所包含的方法解析出来,实际测试下来,如果是用接口实现的话有时候也没办法。不过总体来说这个插件还是不错的。

安装方法:这里就不展开讲了,ctrl + shift + P打开命令窗口,输入install package,加载好列表后,输入GoSublime,回车确认。

另外比较重要的是Golang文件在Sublime中的build system文件,我是这么写的:

{
  "working_dir": "${file_path}",
  "cmd": ["cmd", "/C", "go build -o ${file_base_name}.exe"],
   "shell": true,
  "variants":
  [
     {
          "name": "Run",
          "working_dir": "${file_path}",
          "cmd": ["cmd","/C","start","cmd", "/C", "${file_base_name}.exe &pause"]
     },
     {
        "name" : "Test",
        "working_dir": "${file_path}",
        "cmd": ["cmd","/C","start","cmd", "/C", "go test &pause"]
     }
  ]
}

编译时直接ctrl + shift +B选第一个,运行时ctrl + shift +B选第二个,非常简单,选第三个进行golang的单元测试。

STM32开发入门系列之七:SPI通信

SPI通信是一种高效的同步通信协议,通过4根引脚,实现了数据的高速双向通信。这4根针分工特别简单,简要说明一下:

  • NSS,使能信号,可定义高电平使能或者低电平使能
  • SCK,时钟信号,由主机发起。上升沿之前,主机设置好需要写给从机的值,供从机在高电平的时候读取;下降沿之前,从机设置好需要写给主机的值,供主机在下降沿读取。
  • MISO,主机输入,从机输出引脚。(M:master 主机,S:slaver 从机)
  • MOSI,主机输出,从机输入引脚。

根据STM32的引脚定义手册,我们可以清晰地看到PA4,PA5,PA6,PA7分别对应上面的NSSS,SCK,MISO,MOSI,截图如下:

下面是我自己用的STM32作为下位机使用SPI跟上位机通信的DEMO,秉承一贯的风格,注释详细到令人发指,就不多解释了。

#include "stm32f10x.h"

volatile u16 data[16];
volatile u8 index = 0;
volatile u8 flag  = 0;  //通知主函数处理IO事件的信号量,1:需要处理,0:不需要处理

volatile u32 time = 0;  //SPI信号中的时间偏移量,过大的话,认为是第二组SPI数据

void SPIInit(void) {
    /* 中断向量配置 */
    NVIC_InitTypeDef nvicInitTypeDef;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    nvicInitTypeDef.NVIC_IRQChannel = SPI1_IRQn;
    nvicInitTypeDef.NVIC_IRQChannelPreemptionPriority = 0;
    nvicInitTypeDef.NVIC_IRQChannelSubPriority = 2;
    nvicInitTypeDef.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvicInitTypeDef);

    /* GPIO 设置 */

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);

    GPIO_InitTypeDef  GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_Init(GPIOA , &GPIO_InitStructure);

    /*
     *  SPI 管脚配置
     *  PA4 ---- NSS
     *  PA5 ---- SCK
     *  PA6 ---- MISO
     *  PA7 ---- MOSI
     */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA , &GPIO_InitStructure);

    /* spi config */
    SPI_InitTypeDef spiInitStructure;

    /* spi 初始化定义 */
    spiInitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线读写
    spiInitStructure.SPI_Mode      = SPI_Mode_Slave;                  //从模式
    spiInitStructure.SPI_DataSize  = SPI_DataSize_8b;                 //8位每帧
    spiInitStructure.SPI_CPOL      = SPI_CPOL_Low;                    //时钟空闲为低
    spiInitStructure.SPI_CPHA      = SPI_CPHA_1Edge;                  //数据捕获于第一个时钟沿
    spiInitStructure.SPI_NSS       = SPI_NSS_Hard;                    //硬件控制NSS信号
    spiInitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //波特率预分频
    spiInitStructure.SPI_FirstBit  = SPI_FirstBit_MSB;                //数据传输从MSB位开始
    spiInitStructure.SPI_CRCPolynomial = 7;                           //CRC设置,不启用
    SPI_Init(SPI1, &spiInitStructure);

    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);                  //使能接收中断

    SPI_Cmd(SPI1, ENABLE);                                            //使能SPI1
}

/* SPI 中断控制函数 */
void SPI1_IRQHandler(void) {
    if(SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET){
        u16 buff = 0;
        buff = SPI_I2S_ReceiveData(SPI1);
        if(time > 9000 || index == 0) {
            //时间过大或者index本身为0,认为新数据
            index = 0;
            if(buff == 0xAA){
                //包头            
                data[index] = buff;
                index++;
            }            
        }else if(index == 10){
            //checksum校验

            //校验通过的话,通知主函数处理IO
            index = 0;
            flag  = 1;
        }else if(index < 9 && index >= 1){
            //IO数据中的字节
            data[index] = buff;
            index++;
        }
    }
    time = 0;
}

int main(void) {
    SystemInit();

    index = 0;
    flag  = 0;

    SPIInit();
    GPIO_SetBits(GPIOA, GPIO_Pin_0);

    while(1) {
        time++;
        if(flag){
            flag = 0;
            //处理IO数据
            if(data[1] & 0x0080)
                GPIO_SetBits(GPIOA, GPIO_Pin_0);
            else
                GPIO_ResetBits(GPIOA, GPIO_Pin_0);
        }
    }
}

这个系列写到第七章,STM32相关的知识也就差不多了,以后我接触到更好的知识点,在自己弄明白的基础上,再陆陆续续更新这个系列。

丁丁生于 1987.07.01 ,30岁,英文ID:newflydd

  • 现居住地 江苏 ● 泰州 ● 姜堰
  • 创建了 Jblog 开源博客系统
  • 坚持十余年的 独立博客 作者
  • 大学本科毕业后就职于 中国电信江苏泰州分公司,前两年从事Oracle数据库DBA工作,两年后公司精简技术人员,被安排到农村担任支局长(其本质是搞销售),于2016年因志向不合从国企辞职,在小城镇找了一份程序员的工作。
  • Git OSChina 上积极参与开源社区