tag 标签: io口

相关博文
  • 热度 17
    2016-2-9 19:26
    1200 次阅读|
    1 个评论
    学stm32的过程中,掌握IO口是很重要的基础。这篇博文简单介绍一下stm32的IO口。 一、 IO 口的基本操作 ( 1 ) IO 口模式: GPIO_Mode_IN 输入模式,输入 3.3V或 0V 的 高低电平。例如按键程序就是配置称输入模式 GPIO_Mode_OUT 输出模式,输出 3.3V或 0V 的 高低电平。例如 LED 闪烁程序配置成输出模式。 GPIO_Mode_AF 复用工作模式。例如 I2C , SPI , USART 。 GPIO 就必须配成 AF 模式。   GPIO_Mode_AN 模拟输入模式。例如 ADC 程序必须配置成 AN 模拟量输入模式。 ( 2 )当配置成输出模式或者 AF 模式时,输出类型有两种: GPIO_OType_PP 推挽输出,即可输出高电平,也可以输出低电平。   GPIO_Otype_OD 开漏输出,只能输出低电平。 ( 3 )无论是输入还是输出,都可以配置上下拉类型: GPIO_PuPd_NOPULL 不上下拉 GPIO_PuPd_UP 上拉模式   GPIO_PuPd_DOWN 下拉模式 ( 4 )下面具体看下什么是推挽输出,什么是开漏输出,以及它们的特点。 推挽输出 GPIO_OType_PP 特点:   既可输出高电平,也可以输出低电平。如下图: 当我们将 GPIO 配置成低电平的, Q1 截止, Q2 导通, S2 输出低电平; 当我们将 GPIO 配置成高电平的, Q1 导通, Q2 截止, S2 输出高电平;   其实黑色区域是在单片机的内部,因此它的电流是单片机的电流,所以说它驱动能力是较弱的。 ( 5 )开漏输出 GPIO_OType_PP 的特点: 只能输出低电平,不能输出高电平。 其优点在于: 大电流驱动能力; 电平匹配; 可以实现“线与”功能。 逻辑框图如下 : 当往 IO 写 0 时: S1 为低电平, Q1 截止,因此 Q2 的基极就是 VCC 为高, Q2 导通, S2 输出被拉到 GND ,因此输出低电平。 当往 IO 写 1 时, S2 为高电平, Q1 导通,因此 Q2 的基极被拉到 GND 为低, Q2 截止, S2 输出是不确定的。   因此开漏输出只能输出低电平。 S2 直接从 Q2 的集电极引出,所以呀开漏输出也成为集电极开漏输出。 其实你也可以开漏输出高电平的。那么如何让开漏输出输高电平呢?其实很简单。(这个过渡段好苍白。。。) 只要在开漏的输出加上一个上拉电阻,就可以输出高电平了 (VCC1 是单片机内部电源, VCC2 是外部电源 ) ,流过 R3 的电流是由外部电源提供,所以说这种电流可以提供较大的电流。   例如: VCC1 是 3.3V (开发板), VCC2 是 5v 时 S2 就可以输出 OV 和 5V ,从而实现了电平转换。也就是说开漏输出有电平转换的功能。 开漏输出的应用:线与功能 只有当 S1 , S3 , S5 输入全为高电平时输出才是高电平,当 S1 , S3 , S5 ,中有任意一个为低电平是输出就为低电平。这就是所谓的线与功能。   例如 I2C 总线 各器件的 SDA 和 SCL 都是线“与”关系。 (6) IO 口上下拉 作用: 将不确定的信号通过一个电阻,嵌位在确定电平; 为开漏型电路输出电流通道; 在一定程度上提高系统的抗干扰;   例如串口 RS485 电路的方向控制。 RS485 电路是半双工的收发不能同时进行。  
  • 热度 28
    2011-5-30 16:51
    3292 次阅读|
    3 个评论
    由于项目所需,所以这段时间,抽空学了一下LPC2134,它是基于ARM7核的微处理器,内部有128K的flash与16k的RAM,所以一般的处理程序,内部空间就够用了,当然你要上想在上面跑跑操作系统什么的,那就另当别论了。关于这个处理器其它方面的内部资料,如果你想了解,建议你好好翻翻它的数据手册,如果你说英文太难啃,网上有大把中文的资料,当然懒猫还是建议你看英文原版,一它是厂家的资料,比较真实可靠一般不会有什么大错,二你还可以凑这个空档学学英语,真学好了这也是你要工资的筹码。   今天只是实验一下它的IO端口功能,如何实验,懒猫就不再从流水灯开始了,懒猫选择从LCD12864开始,说实在看着这么大一块屏,挺吓人的,其实LCD也没有那么可怕,处理好时序就能让它乖乖的显示,所以想写好LCD12864的驱动首先还是要好好翻看它的数据手册,这里懒猫就不再详述数据手册上的内容了。不过在这里懒猫要先啰嗦一句,想让LCD12864正确显示,一定要记住先清屏,其实也就是清它内部寄存器,否则初始化时它内部的RAM中不知道是什么乱七八糟的东东,一旦你没有清屏,很可能在显示时会出现乱码或显示不正常,如下图所示: 图1-1 初始化时没有加清屏函数 其实懒猫在上大学时就试着用51写LCD12864的驱动程序,所以这次使用还算顺利,记得当时初次使用LCD12864出现这种情况,懒猫非常郁闷,以为自己的驱动程序没有写好,于是使劲翻看数据手册,仔细的看时序,最后还单步调试,发现问题还是没有解决,最后懒猫看到LCD12864中RAM时,突然想到单片机的设置变量时,初值也是随机的,于是就想着清一下RAM,结果问题还真解决了,呵呵,当时那个兴奋呀,无以言表。现在想想那时真的有点傻的可爱,网上有好多现成的程序,自己却一个人死扣自己的程序。可惜时光如梭,转眼间懒猫毕业就要两年了,那些激情燃烧的岁月已渐渐远去,却永远无法抹去我美好的记忆……   好了,不费话,说一说这次测试的电路,外围电路很简单,没有接什么东东,就接了一块LCD12864,2134的晶振是12MHz的,实时时钟频率是32.768KHz,下面给出仿真电路图,上面省略了很多东东,这次仿真用的是proteus7.5的版本,仿真不能代替实物,懒猫的程序都是通过实物测试通过的,仿真只是为了调试之用,如果你真想学到真本领,做项目是最好的途径。 图2 电路仿真图 注意,这是仿真电路图,实际设计中要加上电源,晶振,电位器等部件,这个电路图只说明一下LCD与LPC2134的数据接口。   说一下程序,程序包括main.c与display.c两个C源程序代码,只是简单的测试一下lpc2134与LCD12864为后面的实验做一个铺垫,以后的实验可能会用到这个驱动,由于程序东东比较多,所以就只贴出display.c这个源程序,其它的程序在附件中,如果有兴趣可以下载下来查看: /*************************************************************************/ //文件名称:display.c //功    能:LCD12864驱动函数 //作    者:懒猫爱飞 //备    注:MCU      -- LPC2134 //          Crystal  -- 12MHz //          RTC      -- 32.768KHz   //          开发环境 -- RealView MDK-ARM Verxion 4.12 /*************************************************************************/ #define IN_DISPLAY   #include "config.h" #include "display.h"   //LCD12864引脚配置 #define LCD_CS1 4     /*-- P0.4 --*/ #define LCD_CS2 3     /*-- P0.3 --*/ #define LCD_RST 5     /*-- P0.5 --*/ #define LCD_DI  21    /*-- P0.21 --*/ #define LCD_RW  11    /*-- P0.11 --*/ #define LCD_EN  10    /*-- P0.10 --*/   //LCD12864操作宏定义 #define LCD_DE() IO0SET |= 1     #define LCD_IE() IO0CLR |= 1     #define LCD_RE() IO0SET |= 1     #define LCD_WE() IO0CLR |= 1     #define LCD_EH() IO0SET |= 1     #define LCD_EL() IO0CLR |= 1         //LCD12864命令宏定义 #define LCDSTARROW 0xC0    /*-- 设置起始行指令 --*/ #define LCDPAGE    0xB8    /*-- 设置页指令 --*/ #define LCDLINE    0x40    /*-- 设置列指令 --*/   /********************************************************************************** //函数名称:void delay_us(void) //功    能:简短微秒级延时 //入口参数:uint32 t -- 延时长度 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void delay_us(uint32 us) {     while(us--);      }   /********************************************************************************** //函数名称:void Out_Data(uint8 Odata) //功    能:向端口输出数据 //入口参数:uint8 Odata -- 要输出的数据 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Out_Data(uint8 Odata) {     IO1CLR |= (uint32)(0xFF16);  // 将输出端口置0     IO1SET |= (uint32)(Odata16); // 输出要输出的数据Odata }   /********************************************************************************** //函数名称:void Write_Data(uint8 Wdata) //功    能:向LCD12864端口写入数据 //入口参数:uint8 Wdata -- 要写入的数据 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Write_Data(uint8 Wdata) {     LCD_DE();        // 写数据使能     delay_us(1);     // 延时等待端口电平稳定        LCD_WE();        // 写命令使能     delay_us(1);     // 延时等待数据写进端口寄存器     Out_Data(Wdata); // 输出要写入LCD12864的数据     delay_us(1);     // 延时等待端口电平稳定     LCD_EH();        // 数据在EN下降沿写入LCD12864中     delay_us(3);     // 延时     LCD_EL();        // EN下降沿     delay_us(3);     // 延时一下 }   /********************************************************************************** //函数名称:void Write_Cmd(uint8 Wcmd) //功    能:向LCD12864端口写入命令 //入口参数:uint8 Wcmd -- 要写入的命令 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Write_Cmd(uint8 Wcmd) {     LCD_IE();        // 写命令使能     delay_us(1);     LCD_WE();        // 写命令使能     delay_us(1);       Out_Data(Wcmd);  // 写入命令     delay_us(1);     LCD_EH();        // 数据在EN下降沿写入LCD12864中     delay_us(3);         LCD_EL();        // EN下降沿     delay_us(3);                                      }   /********************************************************************************** //函数名称:void Init_LCDIO(void) //功    能:LCD端口初始化函数 //入口参数:NULL //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Init_LCDIO(void) {     IO0DIR |=  (1 )                    |(1 )                                   |(1 )                                   |(1 )                                   |(1 )                                   |(1 );     IO0SET |= (1 )|(1     IO0CLR |= 1     IO0CLR |= 1 ;                    delay_us(50);     IO0SET |= 1 ;                    delay_us(50);     IO0SET |= (1 )|(1     Write_Cmd(0x3F);                     //开显示, 关显示为 -- 0x3e     Write_Cmd(0x38);                                        // 8位形式,两行字符     Write_Cmd(0x0F);                     // 开显示     Write_Cmd(0x01);                     // 清屏     Write_Cmd(0x06);                     // 画面不动,光标右移     Write_Cmd(0xC0);                     // 设置起始行 }   /********************************************************************************** //函数名称:void Show_Row(uint8 ucPage,uint8 ucLine,uint8 ucWidth,uint8 const *ucaRow) //功    能:在8×128的格子里显示自定义长度的一行 //入口参数:uint8 ucPage   -- 取值范围0~7 //          uint8 ucLine   -- 取值范围0~127 //          uint8 ucWidth  -- 取值范围0~127 //          ucLine+ucWidth1128 //          uint8 const *ucaRow    -- 要显示的数组 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Show_Row(uint8 ucPage,uint8 ucLine,uint8 ucWidth,uint8 const *ucaRow) {     uint8 ucCount = 0;     if(ucLine64)     {         IO0SET |= 1 ;                              IO0CLR |= 1 ;                   Write_Cmd(LCDPAGE+ucPage);     // 设定页号                   Write_Cmd(LCDLINE+ucLine);     // 设定列号                   Write_Cmd(0x34);                   if(ucLine+ucWidth64)          // 位于左半屏                   {                                 for(ucCount = 0;ucCount ;uccount++)                                 {                                               Write_Data(*(ucaRow+ucCount));   // 写入数据                                 }                               }                   else                                    // 跨越两个半屏 先写完左半屏                   {                                 for(ucCount=0;ucCount64-ucLine;ucCount++)                                 {                                                Write_Data(*(ucaRow+ucCount));              // 写入数据                                 }                                   IO0CLR |= 1 ;                                                IO0SET |= 1 ;                       Write_Cmd(LCDPAGE+ucPage);          // 设定页号                       Write_Cmd(LCDLINE);                 // 设定列号                                 Write_Cmd(0x34);                                  for(ucCount=64-ucLine;ucCount ;uccount++)                                 {                                                 Write_Data(*(ucaRow+ucCount));// 写入数据                                 }                                                                                                                   }     }     else                                    // 位于右半屏     {                   IO0CLR |= 1 ;                                            IO0SET |= 1 ;                   Write_Cmd(LCDPAGE+ucPage);          // 设定页号                   Write_Cmd(LCDLINE+ucLine-64);       // 设定列号                   Write_Cmd(0x34);                   for(ucCount=0;ucCount ;uccount++)                   {                                 Write_Data(*(ucaRow+ucCount));  // 写入数据                              }     } }    /********************************************************************************** //函数名称:void Show_Onehz(uint8 ucPage,uint8 ucLine,uint8 const *ucaChinMap) //功    能:将16×16汉字显示在8×128的格子里 //入口参数:uint8 ucPage -- 取值范围 0~7 //          uint8 ucLine -- 取值范围 0~127 //          int8 const *ucaChinMap -- 要显示的汉字数组 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Show_Word(uint8 ucPage,uint8 ucLine,uint8 const *ucaChinMap) {     Show_Row(ucPage,ucLine,16,ucaChinMap);                                      // 汉字上半部分     Show_Row(ucPage+1,ucLine,16,ucaChinMap+16);                          // 汉字下半部分 }   /********************************************************************************** //函数名称:void Display_HZ(uint8 pagenum,uint8 colnum,uint8 num) //功    能:LCD显示汉字 //入口参数:uint8 pagenum -- 页码 //          uint8 colnum  -- 列数 //          uint8 num     -- 第几个汉字 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Display_HZ(uint8 pagenum,uint8 colnum,uint8 num) {   //uint8 k;   uint8 const *p1;   //k=colnum*16;   p1=hz_mode ;   Show_Word(pagenum,colnum,p1); } /********************************************************************************** //函数名称:void Show_Char(uint8  ucPage,uint8  ucLine,uint8  const *ucaCharMap) //功    能:将8×16字符显示在8×128的格子里。 //入口参数:uint8  ucPage – 要写入的页 //           uint8  ucLine – 要写入的列 //           uint8  const *ucaCharMap – 要写入的数值 //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Show_Char(unsigned char ucPage,unsigned char ucLine,unsigned char const *ucaCharMap) {     Show_Row(ucPage,ucLine,8,ucaCharMap);     Show_Row(ucPage+1,ucLine,8,ucaCharMap+8); } /********************************************************************************** //函数名称:void Clear_Screen() //功    能:清屏函数 //入口参数:NULL //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Clear_Screen() {    uint8 i,j;    for(i=0;i8;i+=2)   //共8页    {       for(j=0;j128;j+=8)     //共128列       {         Show_Char(i,j,CHAR_B);       }    } } /********************************************************************************** //函数名称:void Init_LCD(void) //功    能:LCD初始化函数 //入口参数:NULL //出口参数:NULL //备    注:NULL ***********************************************************************************/ void Init_LCD(void) {     Init_LCDIO();    // 初始化LCD接口     Clear_Screen();  // 要先清屏,不然会显示不正常       /*-- 以下显示函数显示“懒猫爱飞,学习日志” --*/     Display_HZ(2,0,10);     // 懒     Display_HZ(2,16,11);    // 猫     Display_HZ(2,32,12);    // 爱     Display_HZ(2,48,13);    // 飞       Display_HZ(3,64,14);    // 学     Display_HZ(3,80,15);    // 习     Display_HZ(3,96,16);    // 日     Display_HZ(3,112,17);   // 志 } 当然这个程序还不完善,还没显示图片的函数,以后会慢慢加上的,现在还只是在LPC2134中裸奔,主要是为了了解一下它内部结构与内部资源,以后的资料会涉及到ucos可其它嵌入式系统,这个慢慢再总结。 好了,今天说就先到这吧 最后再吼一下懒猫的口号:   每天进步一点点,开心多点 ^_^  
相关资源
  • 所需E币: 4
    时间: 2019-12-25 21:16
    大小: 13KB
    上传者: 二不过三
    单片机又称单片微控制器,它是把一个计算机系统集成到一个芯片上,概括的讲:一块芯片就成了一台计算机。单片机技术是计算机技术的一个分支,是简易机器人的核心元件。……
  • 所需E币: 4
    时间: 2019-12-25 21:14
    大小: 28.5KB
    上传者: quw431979_163.com
    单片机要自动完成计算,它应该具有哪些最重要的部分呢?我们以打算盘为例计算一道算术题。例:36+163×156-166÷34。现在要进行运算,首先需要一把算盘,其次是纸和笔。我们把要计算的问题记录下来,然后第一步先算163×156,把它与36相加的结果记在纸上,然后计算166÷34,再把它从上一次结果中减去,就得到最后的结果。……
  • 所需E币: 5
    时间: 2019-12-25 12:06
    大小: 2.01MB
    上传者: wsu_w_hotmail.com
    MCS51的基本结构及工作原理……
  • 所需E币: 4
    时间: 2019-12-25 11:30
    大小: 17.42KB
    上传者: 2iot
    在通常矩阵键盘的基础上扩充组成一种双矩阵键盘。新增键盘的行线经过三极管倒相之后并接到原键盘的行线上,如此在扫描码取反时,就能够查询新增键盘的按键。用这种扩展有效扫描码的方法,实现在耗用相同I/O口的情况下,将按键的数量增加了一倍。……
  • 所需E币: 5
    时间: 2019-12-25 10:49
    大小: 45.92KB
    上传者: quw431979_163.com
    单片机原理及应用……
  • 所需E币: 3
    时间: 2019-12-25 10:22
    大小: 677.63KB
    上传者: wsu_w_hotmail.com
    嵌入式系统——硬件结构……
  • 所需E币: 3
    时间: 2019-12-25 10:23
    大小: 166.49KB
    上传者: 238112554_qq
    MCS51单片机的系统扩展技术4……
  • 所需E币: 4
    时间: 2019-12-25 10:23
    大小: 96.76KB
    上传者: 2iot
    MCS51单片机的系统扩展技术3……
  • 所需E币: 4
    时间: 2019-12-25 10:22
    大小: 304.3KB
    上传者: 978461154_qq
    嵌入式系统——串行输入输出接口……
  • 所需E币: 3
    时间: 2019-12-25 09:51
    大小: 24KB
    上传者: quw431979_163.com
    51IO口模拟串口通讯C源程序#include sbit BT_SND =P1^0;sbit BT_REC =P1^1;/**********************************************IO 口模拟232通讯程序使用两种方式的C程序 占用定时器0 **********************************************/#define MODE_QUICK#define F_TM F0#define TIMER0_ENABLE  TL0=TH0; TR0=1;#define TIMER0_DISABLE TR0=0;sbit ACC0=   ACC^0;sbit ACC1=   ACC^1;sbit ACC2=   ACC^2;sbit ACC3=   ACC^3;sbit ACC4=   ACC^4;sbit ACC5=   ACC^5;sbit ACC6=   ACC^6;sbit ACC7=   ACC^7;void IntTimer0() interrupt 1{F_TM=1;}//发送一个字符void PSendChar(unsigned char inch){#ifdef MODE_QUICK ACC=inch;F_TM=0;BT_SND=0; //start bit TIMER0_ENABLE; //启动while(!F_TM);BT_SND=ACC0; //先送出低位F_TM=0;while(!F_TM);BT_SND=ACC1; F_TM=0;while(!F_TM);BT_SND=ACC2; F_TM=0;while(!F_TM);BT_SND=ACC3; F_TM=0;while(!F_TM);BT_……
  • 所需E币: 3
    时间: 2020-1-6 14:09
    大小: 20KB
    上传者: 238112554_qq
    IO口模拟串口通讯C源程序……