基于FPGA的I2C读写EEPROM
I2C在芯片的配置中应用还是很多的,比如摄像头、VGA转HDMI转换芯片,之前博主分享过一篇I2C协议的基础学习IIC协议学习笔记,这篇就使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用。
EEPROM
我使用的这个芯片是AT24C32,它手册上还有一种AT24C64,其实操作都是一样的,只是内存大小不同,AT24C32是32k(4096x8)AT24C64是64k(9=8192x8),
SCL设置为频率200Khz
SCL clk posedge data输入EEPROM
SCL clk negedge data输出EEPROM
SDA 双向Pin
A2,A1,A0 Device Addr default all 0,只操作一片可悬空引脚。
WP 接地正常读写,WP接Vcc写操作被禁止
字节寻址地址,是由12(AT24C32)或13bit(AT24C64)的地址组成,需要操作16位字地址高3或4位忽略即可。
Device Address 8’hA0写器件地址,8’hA1读器件地址
写字节操作
随机读字节操作
我这个芯片是双字节数据地址,所以在写数据地址时要写两次,先是高字节后是低字节。
开始结束标志
这个I2C总线的时序是一致的。
EEPROM应答
输出应答scl的第九个周期给出,低电平应答。如果主机没有收到应答,需要重新配置。
数据传输时序
sda数据线在scl时钟的下降沿中间变化,可以避免产生误触开始结束标志。
I2C Design
i2c_start为高电平有效,传输完成后会产生一个i2c_done结束标志,表示操作完成。
I2C状态转移图
I2C写操作
(1)产生start位
(2)传送器件地址ID_Address,器件地址的最后一位为数据的传输方向位,R/W,低电平0表示主机往从机写数据(W),1表示主机从从机读数据(R)。这里按照手册给出的操作图,应该是W即低电平。ACK应答,应答是从机发送给主机的应答,这里不用管。
(3)传送写入器件寄存器地址,即数据要写入的位置。同样ACK应答不用管。
(4)传送要写入的数据。ACK应答不用管。
(5)产生stop信号。
I2C读操作
(1)产生start信号
(2)传送器件地址(写ID_Address),这里按照手册给出的操作图,最低位是W即低电平。ACK。
(3)传送字地址(写REG_Address),ACK。
(4)再次产生start信号
(5)再传送一次器件地址,这里根据手册最低位是读R高电平,ACK。
(6)读取一个字节的数据,读数据最后结束前无应答ACK信号。
(7)产生stop信号。
读写操作的写器件地址和写数据地址操作是一样的,状态转移图中读写操作中这两部分复用了,根据读写标志来判断。
其他部分没啥好说的根据时序图写就行了,需要注意的一点是我们应该在sclk的高电平的中间采样数据,在sclk低电平的中间改变数据,当sclk为高电平的时候,sda为出现下降沿为start位, sda出现上升沿为stop位,所以在sclk为高电平的时候sda应该保持稳定不能随意乱动。这就又回到了数据传输有效的条件,只有在sclk为低电平期间,才允许数据变化,在高电平期间,不允许数据变化,否则就会出现起始位或结束位。
EEPROM有个仿真模型,在夏雨闻老师的书里面就有,这个模型默认是200khz的sclk驱动,仿真的时候可以将时间参数改小,我这里也分享出来。
仿真模型代码
`timescale 1ns/1ns
`define timeslice
//`define timeslice 300 module EEPROM_AT24C64(
scl,
sda
);
input scl; //串行时钟线
inout sda; //串行数据线 reg out_flag; //SDA数据输出的控制信号 reg[:] memory[:]; //数组模拟存储器
reg[:]address; //地址总线
reg[:]memory_buf; //数据输入输出寄存器
reg[:]sda_buf; //SDA数据输出寄存器
reg[:]shift; //SDA数据输入寄存器
reg[:]addr_byte_h; //EEPROM存储单元地址高字节寄存器
reg[:]addr_byte_l; //EEPROM存储单元地址低字节寄存器
reg[:]ctrl_byte; //控制字寄存器
reg[:]State; //状态寄存器 integer i; //---------------------------
parameter
r7 = 'b1010_1111, w7 = 8'b1010_1110, //main7
r6 = 'b1010_1101, w6 = 8'b1010_1100, //main6
r5 = 'b1010_1011, w5 = 8'b1010_1010, //main5
r4 = 'b1010_1001, w4 = 8'b1010_1000, //main4
r3 = 'b1010_0111, w3 = 8'b1010_0110, //main3
r2 = 'b1010_0101, w2 = 8'b1010_0100, //main2
r1 = 'b1010_0011, w1 = 8'b1010_0010, //main1
r0 = 'b1010_0001, w0 = 8'b1010_0000; //main0
//--------------------------- assign sda = (out_flag == ) ? sda_buf[] : 'bz; //------------寄存器和存储器初始化---------------
initial
begin
addr_byte_h = ;
addr_byte_l = ;
ctrl_byte = ;
out_flag = ;
sda_buf = ;
State = 'b00;
memory_buf = ;
address = ;
shift = ; for(i=;i<=;i=i+)
memory[i] = ;
end //启动信号
always@(negedge sda)
begin
if(scl == )
begin
State = State + ;
if(State == 'b11)
disable write_to_eeprom;
end
end //主状态机
always@(posedge sda)
begin
if(scl == ) //停止操作
stop_W_R;
else
begin
casex(State)
'b01:begin
read_in;
if(ctrl_byte == w7 || ctrl_byte == w6
|| ctrl_byte == w5 || ctrl_byte == w4
|| ctrl_byte == w3 || ctrl_byte == w2
|| ctrl_byte == w1 || ctrl_byte == w0)
begin
State = 'b10;
write_to_eeprom; //写操作
end
else
State = 'b00;
//State = State;
end 'b11:
read_from_eeprom; default:
State = 'b00;
endcase
end
end //主状态机结束 //操作停止
task stop_W_R;
begin
State = 'b00;
addr_byte_h = ;
addr_byte_l = ;
ctrl_byte = ;
out_flag = ;
sda_buf = ;
end
endtask //读进控制字和存储单元地址
task read_in;
begin
shift_in(ctrl_byte);
shift_in(addr_byte_h);
shift_in(addr_byte_l);
end
endtask //EEPROM的写操作
task write_to_eeprom;
begin
shift_in(memory_buf);
address = {addr_byte_h[:], addr_byte_l};
memory[address] = memory_buf;
State = 'b00;
end
endtask //EEPROM的读操作
task read_from_eeprom;
begin
shift_in(ctrl_byte);
if(ctrl_byte == r7 || ctrl_byte == w6
|| ctrl_byte == r5 || ctrl_byte == r4
|| ctrl_byte == r3 || ctrl_byte == r2
|| ctrl_byte == r1 || ctrl_byte == r0)
begin
address = {addr_byte_h[:], addr_byte_l};
sda_buf = memory[address];
shift_out;
State = 'b00;
end
end
endtask //SDA数据线上的数据存入寄存器,数据在SCL的高电平有效
task shift_in;
output[:]shift;
begin
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda;
@(posedge scl) shift[] = sda; @(negedge scl)
begin
#`timeslice;
out_flag = ; //应答信号输出
sda_buf = ;
end @(negedge scl)
begin
#`timeslice;
out_flag = ;
end
end
endtask //EEPROM存储器中的数据通过SDA数据线输出,数据在SCL低电平时变化
task shift_out;
begin
out_flag = ;
for(i=; i>=; i=i-)
begin
@(negedge scl);
#`timeslice;
sda_buf = sda_buf << ;
end
@(negedge scl) #`timeslice sda_buf[] = ; //非应答信号输出
@(negedge scl) #`timeslice out_flag = ;
end
endtask endmodule
//eeprom.v文件结束
根据仿真模型仿真的话基本不会有什么问题,需要注意的是操作的完成标志。从仿真上看到输入读写都没问题,但是stop标志没产生好,仿真看到读写操作没问题,但实际还是不行的,需要严格按照EEPROM的手册操作时序进行,差一点就不行。
I2C的代码我分享出来,我最后使用拨码开关作为读写使能,数码管显示读出来的输出,最后实现了对指定存储地址读写数据。
I2C设计代码点击阅读原文可以查看。
`timescale 1ns/1ps
// *********************************************************************************
// Project Name :
// Author : NingHeChuan
// Email : ninghechuan@foxmail.com
// Blogs : http://www.cnblogs.com/ninghechuan/
// File Name : I2C_Ctrl_EEPROM.v
// Module Name :
// Called By :
// Abstract :
//
// CopyRight(c) 2018, NingHeChuan Studio..
// All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// 2018/8/15 NingHeChuan 1.0 Original
//
// ********************************************************************************* module I2C_Ctrl_EEPROM(
input clk,
input rst_n,
input [:] eeprom_config_data,
input i2c_start, //1 valid
inout i2c_sdat,
output i2c_sclk,
output i2c_done,
output reg [:] i2c_rd_data
); //-------------------------------------------------------
parameter I2C_IDLE = 'd0;
parameter I2C_START = 'd1;
parameter I2C_WR_IDADDR = 'd2;
parameter I2C_WR_ACK1 = 'd3;
parameter I2C_WR_REGADDR1 = 'd4;
parameter I2C_WR_ACK2 = 'd5;
parameter I2C_WR_REGADDR2 = 'd6;
parameter I2C_WR_ACK3 = 'd7;
parameter I2C_WR_DATA = 'd8;
parameter I2C_WR_ACK4 = 'd9;
parameter I2C_WR_STOP = 'd10;
//-------------------------------------------------------
parameter I2C_RD_START = 'd11;
parameter I2C_RD_IDADDR = 'd12;
parameter I2C_RD_ACK = 'd13;
parameter I2C_RD_DATA = 'd14;
parameter I2C_RD_NPACK = 'd15;
parameter I2C_RD_STOP = 'd16;
//i2c_sclk freq
parameter I2C_FREQ = ; //50Mhz/200Khz/2 = 125
parameter TRANSFER = ;
parameter CAPTURE = ;
//parameter I2C_FREQ = 60; //50Mhz/200Khz/2 = 125
//parameter TRANSFER = 1;
//parameter CAPTURE = 30;
parameter SEND_BIT = ; //-------------------------------------------------------
reg [:] pre_state;
reg [:] next_state;
//
reg i2c_sdat_r;
wire bir_en;
//
wire transfer_en;
wire capture_en;
reg i2c_sclk_r;
reg [:] sclk_cnt;
//
reg [:] tran_cnt;
//
wire [:] wr_device_addr = {eeprom_config_data[:], 'b0};
wire [:] rd_device_addr = {eeprom_config_data[:], 'b1};
wire wr_rd_flag = eeprom_config_data[];
wire [:] reg_addr1 = eeprom_config_data[:];
wire [:] reg_addr2 = eeprom_config_data[:];
wire [:] wr_data = eeprom_config_data[:];
//
reg wr_ack1;
reg wr_ack2;
reg wr_ack3;
reg wr_ack4;
reg rd_ack1; //-------------------------------------------------------
//i2c_sclk
always @(posedge clk or negedge rst_n)begin
if(rst_n == 'b0)
sclk_cnt <= 'd1;
else if(sclk_cnt == I2C_FREQ - 'b1)
sclk_cnt <= 'd0;
else
sclk_cnt <= sclk_cnt + 'b1;
end always @(posedge clk or negedge rst_n)begin
if(rst_n == 'b0)
i2c_sclk_r <= 'b0;
else if(sclk_cnt >= (I2C_FREQ>>)* && sclk_cnt <= (I2C_FREQ>>)*)
i2c_sclk_r <= 'b1;
else
i2c_sclk_r <= 'b0;
end
//
assign transfer_en = (sclk_cnt == TRANSFER - )? 'b1: 1'b0;
assign capture_en = (sclk_cnt == CAPTURE - )? 'b1: 1'b0; //-------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
if(rst_n == 'b0)
tran_cnt <= 'd0;
else if(tran_cnt == SEND_BIT && transfer_en == 'b1)
tran_cnt <= 'd0;
else if(((next_state == I2C_WR_IDADDR || next_state == I2C_WR_REGADDR1 ||
next_state ==I2C_WR_REGADDR2 || next_state == I2C_WR_DATA ||
next_state == I2C_RD_IDADDR) && transfer_en == 'b1) ||
(next_state == I2C_RD_DATA && capture_en == 'b1))
tran_cnt <= tran_cnt + 'b1;
else
tran_cnt <= tran_cnt;
end //-------------------------------------------------------
//FSM step1
always @(posedge clk or negedge rst_n)begin
if(rst_n == 'b0)
pre_state <= I2C_IDLE;
else
pre_state <= next_state;
end //FSM step2
always @(*)begin
next_state = I2C_IDLE;
case(pre_state)
I2C_IDLE:
if(i2c_start == 'b1 && transfer_en == 1'b1)
next_state = I2C_START;
else
next_state = I2C_IDLE;
I2C_START:
if(transfer_en == 'b1)
next_state = I2C_WR_IDADDR;
else
next_state = I2C_START;
I2C_WR_IDADDR:
if(transfer_en == 'b1 && tran_cnt == SEND_BIT)
next_state = I2C_WR_ACK1;
else
next_state = I2C_WR_IDADDR;
I2C_WR_ACK1:
if(transfer_en == 'b1 && wr_ack1 == 1'b0)
next_state = I2C_WR_REGADDR1;
else if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_WR_ACK1;
I2C_WR_REGADDR1:
if(transfer_en == 'b1 && tran_cnt == SEND_BIT)
next_state = I2C_WR_ACK2;
else
next_state = I2C_WR_REGADDR1;
I2C_WR_ACK2:
if(transfer_en == 'b1 && wr_ack2 == 1'b0)
next_state = I2C_WR_REGADDR2;
else if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_WR_ACK2;
I2C_WR_REGADDR2:
if(transfer_en == 'b1 && tran_cnt == SEND_BIT)
next_state = I2C_WR_ACK3;
else
next_state = I2C_WR_REGADDR2;
I2C_WR_ACK3:
if(transfer_en == 'b1 && wr_ack3 == 1'b0 && wr_rd_flag == 'b0)
next_state = I2C_WR_DATA;
else if(transfer_en == 'b1 && wr_ack3 == 1'b0 && wr_rd_flag == 'b1)
next_state = I2C_RD_START;
else if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_WR_ACK3;
I2C_WR_DATA:
if(transfer_en == 'b1 && tran_cnt == SEND_BIT)
next_state = I2C_WR_ACK4;
else
next_state = I2C_WR_DATA;
I2C_WR_ACK4:
if(transfer_en == 'b1 && wr_ack4 == 1'b0)
next_state = I2C_WR_STOP;
else if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_WR_ACK4;
I2C_WR_STOP:
if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_WR_STOP;
I2C_RD_START:
if(transfer_en == 'b1)
next_state = I2C_RD_IDADDR;
else
next_state = I2C_RD_START;
I2C_RD_IDADDR:
if(transfer_en == 'b1 && tran_cnt == SEND_BIT)
next_state = I2C_RD_ACK;
else
next_state = I2C_RD_IDADDR;
I2C_RD_ACK:
if(transfer_en == 'b1 && rd_ack1 == 1'b0)
next_state = I2C_RD_DATA;
else if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_RD_ACK;
I2C_RD_DATA:
if(transfer_en == 'b1 && tran_cnt == SEND_BIT)
next_state = I2C_RD_NPACK;
else
next_state = I2C_RD_DATA;
I2C_RD_NPACK:
if(transfer_en == 'b1)
next_state = I2C_RD_STOP;
else
next_state = I2C_RD_NPACK;
I2C_RD_STOP:
if(transfer_en == 'b1)
next_state = I2C_IDLE;
else
next_state = I2C_RD_STOP;
default:next_state = I2C_IDLE;
endcase
end //FSM step3
always @(posedge clk or negedge rst_n)begin
if(rst_n == 'b0)
i2c_sdat_r <= 'b1;
else begin
case(next_state)
I2C_IDLE: if(capture_en == 'b1) i2c_sdat_r <= 1'b1;
I2C_START: if(capture_en == 'b1) i2c_sdat_r <= 1'b0;
I2C_WR_IDADDR: if(transfer_en == 'b1) i2c_sdat_r <= wr_device_addr['d7 - tran_cnt];
I2C_WR_REGADDR1:if(transfer_en == 'b1) i2c_sdat_r <= reg_addr1['d7 - tran_cnt];
I2C_WR_REGADDR2:if(transfer_en == 'b1) i2c_sdat_r <= reg_addr2['d7 - tran_cnt];
I2C_WR_DATA: if(transfer_en == 'b1) i2c_sdat_r <= wr_data['d7 - tran_cnt];
I2C_WR_ACK4: if(transfer_en == 'b1) i2c_sdat_r <= 1'b0;
I2C_WR_STOP: if(capture_en == 'b1) i2c_sdat_r <= 1'b1;
I2C_RD_START: if(capture_en == 'b1) i2c_sdat_r <= 1'b0;
I2C_RD_IDADDR: if(transfer_en == 'b1) i2c_sdat_r <= rd_device_addr['d7 - tran_cnt];
I2C_RD_NPACK: if(transfer_en == 'b1) i2c_sdat_r <= 1'b0;
I2C_RD_STOP: if(capture_en == 'b1) i2c_sdat_r <= 1'b1;
default: i2c_sdat_r <= i2c_sdat_r;
endcase
end
end always @(posedge clk or negedge rst_n)begin
if(rst_n == 'b0)begin
i2c_rd_data <= 'b0;
wr_ack1 <= 'b1;
wr_ack2 <= 'b1;
wr_ack3 <= 'b1;
wr_ack4 <= 'b1;
rd_ack1 <= 'b1;
end
else if(capture_en == 'b1)begin
case(next_state)
I2C_WR_ACK1: wr_ack1 <= i2c_sdat;
I2C_WR_ACK2: wr_ack2 <= i2c_sdat;
I2C_WR_ACK3: wr_ack3 <= i2c_sdat;
I2C_WR_ACK4: wr_ack4 <= i2c_sdat;
I2C_WR_STOP: begin
wr_ack1 <= 'b1;
wr_ack2 <= 'b1;
wr_ack3 <= 'b1;
wr_ack4 <= 'b1;
rd_ack1 <= 'b1;
end
I2C_RD_ACK: rd_ack1 <= i2c_sdat;
I2C_RD_DATA: i2c_rd_data['d7 - tran_cnt] <= i2c_sdat;
I2C_RD_STOP:begin
wr_ack1 <= 'b1;
wr_ack2 <= 'b1;
wr_ack3 <= 'b1;
wr_ack4 <= 'b1;
rd_ack1 <= 'b1;
end
default:begin
i2c_rd_data <= i2c_rd_data;
wr_ack1 <= wr_ack1;
wr_ack2 <= wr_ack2;
wr_ack3 <= wr_ack3;
wr_ack4 <= wr_ack4;
rd_ack1 <= rd_ack1;
end
endcase
end
else begin
i2c_rd_data <= i2c_rd_data;
wr_ack1 <= wr_ack1;
wr_ack2 <= wr_ack2;
wr_ack3 <= wr_ack3;
wr_ack4 <= wr_ack4;
rd_ack1 <= rd_ack1;
end
end //-------------------------------------------------------
assign bir_en = (pre_state == I2C_WR_ACK1 || pre_state == I2C_WR_ACK2 || pre_state == I2C_WR_ACK3 ||
pre_state == I2C_WR_ACK4 || pre_state == I2C_RD_ACK || pre_state == I2C_RD_DATA)? 'b0: 1'b1; assign i2c_sdat = (bir_en == 'b1)? i2c_sdat_r: 1'bz; assign i2c_sclk = i2c_sclk_r;
assign i2c_done = (pre_state == I2C_WR_STOP && next_state == I2C_IDLE ||
pre_state == I2C_RD_STOP && next_state == I2C_IDLE)? 'b1: 1'b0; endmodule
转载请注明出处:NingHeChuan(宁河川)
个人微信订阅号:开源FPGA
如果你想及时收到个人撰写的博文推送,可以扫描左边二维码(或者长按识别二维码)关注个人微信订阅号
知乎ID:NingHeChuan
微博ID:NingHeChuan
原文地址:https://www.cnblogs.com/ninghechuan/p/9534893.html
基于FPGA的I2C读写EEPROM的更多相关文章
- STM32F10x_模拟I2C读写EEPROM
Ⅰ.写在前面 说到IIC,大家都应该不会陌生,我们初学单片机的时候或多或少都知道或了解过,甚至使用I2C控制过器件.但是,有多少人真正去深入理解,或者深入研究过I2C通信协议呢? 1.我们有必要学习I ...
- STM32F10x_硬件I2C读写EEPROM(标准外设库版本)
Ⅰ.写在前面 上一篇文章是“STM32F10x_模拟I2C读写EEPROM”,讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程. 上一篇文章主要内容:I2C协议.模 ...
- 第23章 I2C—读写EEPROM—零死角玩转STM32-F429系列
第23章 I2C—读写EEPROM 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...
- 转载:关于STM32硬件I2C读写EEPROM代码实现原理的理解与总结
http://home.eeworld.com.cn/my/space-uid-716241-blogid-655190.html 一.I2C协议简介 I2C是两线式串行总线,用于连接微控制器及其外围 ...
- I2C读写EEPROM—EEPROM简介
EEPROM 是一种掉电后数据不丢失的存储器,常用来存储一些配置信息,以便系统重新上电的时候加载之.EEPOM 芯片最常用的通讯方式就是 I 2C 协议,本小节以 EEPROM 的读写实验为大家讲解如 ...
- STM32F10x_模拟I2C读写_硬件I2C读写
STM32F10x_模拟I2C读写EEPROM STM32F10x_硬件I2C读写EEPROM(标准外设库版本) STM32F10x_硬件I2C主从通信(轮询发送,中断接收)
- 第23章 I2C—读写EEPR
本章参考资料:<STM32F76xxx参考手册>.<STM32F7xx规格书>.库帮助文档<STM32F779xx_User_Manual.chm>及<I2C ...
- 【应用笔记】【AN002】通过iTool2基于MinGW平台读写EEPROM
为了增加大家 DIY 的乐趣,XiaomaGee今天为大家只做了一篇使用iTool2内置的USB转I2C来读写EEPROM的方法和代码. iTool2简介 iTool2为银杏公司面向电子类研发工程师推 ...
- 基于FPGA的DDR3多端口读写存储管理系统设计
基于FPGA的DDR3多端口读写存储管理系统设计 文章出处:电子技术设计 发布时间: 2015/03/12 | 1747 次阅读 每天新产品 时刻新体验专业薄膜开关打样工厂,12小时加急出货 机载 ...
随机推荐
- centos7.2下nginx安装教程
1.准备工作 1)关闭iptables 关闭操作 iptables -t nat -F 查看操作 iptables -t nat -L 2)关闭selinux 查看操作 setenforce 关闭操作 ...
- PAT 1063 计算谱半径(20)(代码)
1063 计算谱半径(20 分) 在数学中,矩阵的"谱半径"是指其特征值的模集合的上确界.换言之,对于给定的 n 个复数空间的特征值 { a1+b1i,⋯,an+ ...
- 关于RNA-Seq数据去接头(Adapter)这事需要讲一讲
关于RNA-Seq数据去接头(Adapter)这事需要讲一讲 RNA-Seq adapter barcode cutadapt 首先来了解一下三个概念: 1.adapter是一段短的序列已知的核酸链, ...
- HDOJ2586 How far away ?
一道LCA模板 原题链接 \(LCA\)模板题,不解释. 倍增版 #include<cstdio> #include<cmath> #include<cstring> ...
- c# 反编译后窗口控件在vs中打不开的修改方法
DialogResult.Cancel System.Windows.Forms.DialogResult.Cancel DialogResult.OK System.Windows.Forms.Di ...
- 语法分析器初步学习——LISP语法分析
语法分析器初步学习——LISP语法分析 本文参考自vczh的<如何手写语法分析器>. LISP的表达式是按照前缀的形式写的,比如(1+2)*(3+4)在LISP中会写成(*(+ 1 2)( ...
- JS Async Callback
AsyncCallback 意义: 异步操作完成时调用的方法 语法1: 构造异步回调对象 AsyncCallback 异步回调对象名asyncCallback = new AsyncCallback( ...
- springboot配置il8n
springMvc下,配置il8n: 1.配置ResourceBundleMessageSource管理国际化资源文件 2.在页面使用fmt标签取出国际化内容 springBoot下,自动配置了il8 ...
- java 中java.util.Arrays类---常用函数记录
java.util.Arrays主要是用来对数组进行操作的类,主要包括以下方法: 1.数组转化列表,得到固定大小的列表,Arrays.asList(...): public static <T& ...
- spring学习 十一 AspectJ-based的通知入门 不带参数的通知
AspectJ-Based方式的AOP,通知类不需要实现任何接口,且前置通知,后置通知,环绕通知,异常通知都可以写在一个类中,下面先实现一个简单的,不带参数的通知. 第一步定义通知类,通知类中的通知( ...