因为要在linux内核中加入一个新模块的驱动,所以先用单片机来看看该模块是如何工作的,同时也回顾了以前所学的C51的知识,都快忘得差不多了,同时也是记录学习的旅程。
1602与串口都是新模块在单片机测试中会用到的知识点,所以先拿来看看效果。
源代码编译链接环境keil2.0
先看看lcd1602与串口的电路图
lcd1602的控制线(RS/RW/EN)分别于单片机的P2^4/P2^5/P2^6相连
对于lcd1602在编写的时候,如果没有判断LCD的忙标志的话,很多时候如果不注意延时的话,很有可能无法显示数据,所以一般在写完指令或者数据后,加一点延时,即可
单片机的RX(P3.0)与max232的R2O相连,即接收从PC过来的数据 TX(P3.1)与max232的T2I相连,即发送单片机的数据
对于DB9 通常我们只有三条线 分别是2(RXD) 3(TXD) 5(GND) 就可以了
main.c
//晶振为11.0592MHz #include <reg52.h> //lcd 1602控制位 sbit RS=P2^4; // 寄存器选择位 1--数据寄存器 0--指令寄存器 sbit RW=P2^5; //读写选择为 1---读 0--写 sbit EN=P2^6; //使能位 高电平有效 #define RS_SET RS=1 //数据寄存器 #define RS_CLR RS=0 //指令寄存器 #define RW_SET RW=1 //读 #define RW_CLR RW=0 //写 #define EN_SET EN=1 //使能有效 #define EN_CLR EN=0 //使能无效 void delay_us(unsigned char n) //微秒级别的延时 { while(n--); } void delay1ms(void) //延时1ms { unsigned int i,j; for(i=4;i>0;i--) for(j=113;j>0;j--); } void delay(unsigned int n) //任意的延时程序 { while(n--) delay1ms(); } void lcd_write_ins(unsigned char ins) //写指令 { RS_CLR; //根据时序图操作 RW_CLR; EN_SET; P0=ins; delay_us(5); EN_CLR; } void lcd_write_data(unsigned char dat) //写数据 { RS_SET; RW_CLR; EN_SET; P0=dat; delay_us(5); EN_CLR; } void lcd_write_str(unsigned char x,unsigned char y,unsigned char *p) //写一串数据 { if(y==0) lcd_write_ins(0x80+x); //写数据寄存器的地址 写在第一行 else lcd_write_ins(0xC0+x); //写在第二行 while(*p) { lcd_write_data(*p); p++; } } void lcd_init() //lcd初始化函数 { lcd_write_ins(0x38); //设置4为总线 双行显示 5*7点阵字符 delay(5); lcd_write_ins(0x38); //设置4为总线 双行显示 5*7点阵字符 delay(5); lcd_write_ins(0x38); //设置4为总线 双行显示 5*7点阵字符 delay(5); lcd_write_ins(0x38); //设置4为总线 双行显示 5*7点阵字符 lcd_write_ins(0x08); //关显示/关光标/关闪烁 lcd_write_ins(0x01); //清屏 lcd_write_ins(0x06); //设置输入模式为光标右移 delay(5); //不可少 lcd_write_ins(0x0F); //开显示 } void serial_init() //串口初始化函数 { SCON=0x50; //设置串口工作方式为1 10位异步收发 并使能接收 //因为设置波特率为9600 晶振11.0592MHz TMOD=0x20; // 设置定时器1的工作方式为2 自动8位重装 TH1=0xFD; //设置定时器1的初值 TL1=0xFD; TR1=1; //启动定时器1 EA=1; //开所有中断 ES=1; //开串行中断 } void main(void) { unsigned char *p="data:"; delay(50); //延时50ms lcd_init(); serial_init(); while(1) { lcd_write_ins(0x01); //清屏 delay(5); //延时5ms 不可少 lcd_write_str(2,0,p); //写数据在第一行 delay(1000); //延时1s } } void serial(void) interrupt 4 //串行中断 { unsigned char temp; //用于存储临时值 if(RI) { RI=0; //清除RI temp=SBUF;//读取缓冲区数据 lcd_write_ins(0xC5); //显示在第二行 lcd_write_data(temp); //将获取到的数据显示在lcd上 delay(1000); SBUF=temp; //发送给电脑 } if(TI) TI=0; //清除TI }
对于C51的中断服务程序,是不能进行参数传递,没有返回值的
对于中断服务程序 interrupt 0 对应的入口地址为0x03 对应的中断为外部中断0
interrupt 1 对应的入口地址为0x0B 对应的中断为定时器中断0
interrupt 2对应的入口地址为0x13 对应的中断为外部中断1
interrupt 3 对应的入口地址为0x1B 对应的中断为定时器中断1
interrupt 4 对应的入口地址为0x23 串行口中断