第十四届智能车队员培训 I/O的使用 数据方向寄存器和数据寄存器的配置 MC9S12D64处理器

I/O的使用 数据方向寄存器和数据寄存器的配置

I/O输入输出的使用:

数据方向寄存器与数据寄存器

寄存器的概念:

寄存器,是集成电路中非常重要的一种存储单元,通常由触发器组成。在集成电路设计中,寄存器可分为电路内部使用的寄存器和充当内外部接口的寄存器这两类。内部寄存器不能被外部电路或软件访问,只是为内部电路的实现存储功能或满足电路的时序要求。而接口寄存器可以同时被内部电路和外部电路或软件访问,CPU中的寄存器就是其中一种,作为软硬件的接口,为广泛的通用编程用户所熟知。
在计算机领域, 寄存器是CPU内部的元件,包括 通用寄存器、专用寄存器和 控制寄存器。寄存器拥有非常高的读写速度,所以在寄存器之间的 数据传送非常快。
寄存器内存阶层中的最顶端,也是系统获得操作资料的最快速途径。寄存器通常都是以他们可以保存的位元数量来估量,
 
输入输出的概念:
输入:从cpu芯片的外围电路将信号传入到cpu芯片内部为输入
输出:从cpu芯片内部将信号传出,或传送到pu芯片的外围电路为输出
 
 
数据方向寄存器:数据方向寄存器为他说控制的端口设置数据传输方向,既设置cpu芯片对应引脚的输入与输出
数据寄存器:设置他所控制的端口引脚的数据
 
MC9S12D64处理器的数据方向寄存器(DDRx)

PORTA、PORTB、PORTE和PORTK端口

DDRx决定对应引脚配置为输出口还是输入口,如果某位为“0”,则对应引脚设定为输入口;如果某位为“1”,则对应引脚设定为输出口。MCU复位后,DDRx值为0x00,引脚默认为输入口。 需要注意的是,PORTE端口是一个特例,它的最低两位只能为输入口,所以PORTE端口的数据方向寄存器最低两位是只读位,读取这两位始终返回“0”。

数据寄存器(Px)

数据寄存器Px中的8位对应每个端口中的相应引脚,如果某端口的引脚被定义为输出时,写入数据寄存器Px中的数值,则从对应引脚输出;如果某端口的引脚被定义为输入时,可以读取数据寄存器Px对应引脚的电平值。 需要注意PORTE端口是一个特例,它的最低两位只能为输入口,所以PORTE端口的数据寄存器最低两位是只读位。

简单演示程序一、

1 #include <hidef.h>      /* common defines and macros */
2 #include "derivative.h"      /* derivative-specific definitions */
3 
4 //************主函数*************
5 void main(void)
6 {
7 DDRA=0x0F;//数据方向寄存器7-0 八位设置为 十六进制数0F 二进制为0000 1111  高四位引脚为输入 低四位引脚为输出
8 PORTA=0x0A;//数据寄存器7-0  八位设置为 十六进制数0A 二进制为0000 1010  高四位引脚悬空 低四位引脚1号和三号输出高电平0号和2号输出低电平
9 }

此时,A端口0号和2号引脚所控制的 LED灯点亮,其余灯灭。

原因:1号和3号引脚因输出高电平而不亮。7号-4号因数据方向寄存器设置为输入状态,因此无法改变LED灯电路控制端(电路开断)

疑问:为什么输出低电平LED灯会亮,高电平不亮?

解答:

在单片机开发的过程中,LED灯的亮灭控制与传统电路开关有所不同。统灯的亮灭控制由电路火线220V的开断所控制,而单片机开发中,LED灯的亮灭大多数需结合单片机实际电路设计来对LED灯的控制端进行控制。

如图:

单片机控制引脚在二极管反向,此二极管功能为开关二极管。二极管在正向电压作用下电阻很小,处于导通状态,相当于一只接通的开关;在反向电压作用下,电阻很大,处于截止状态,如同一只断开的开关。因此当单片机控制引脚为输出低电平时,二极管正向电压>反向电压 电路导通,LED灯亮。

复杂例程:

//*******************************************//
//***         演示程序一                  ***//
// ******************************************//

//*******************************************// 
//*描述:                                   *//
//*   此程序包含以下几个模块:              *//
//*    交通灯、矩阵键盘、继电器、拨码开关   *//
//*                                         *//
//*  目的:                                 *//
//*    完成简单的I/O控制,熟悉基本C语言编程 *//
//*******************************************//


//用拨码开关来控制模块的调用//
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

////////////////////////////////////////////

//全局变量的定义
unsigned int waittime=0;//定义继电器延时计数变量
unsigned int jidianqi_star=0;//定义继电器开关
unsigned int juzhengjianpan_star=0; //矩阵键盘开关
unsigned int paomadeng_star=0;       //跑马灯开关
unsigned int times=0;//跑马灯依次按键计数变量
 
//*************延时********************//
void delay(unsigned int num) //接收无符号延时变量 num
{                                                    
 int i;                   //定义延时变量 i
 //2重循环
 for(num;num>0;num--)                     //num循环减1
 {                                                    
 for(i=100;i>=0;i--);                      //在num循环减1内依次i循环减1
 }
}


//****************继电器模块***********//
void jidianqi(void) //无接收值继电器
{
delay(2000);//定义             num=2000并调用延时函数
   waittime++;    //             继电器延时计数变量waittime+1
 if(waittime<=1)    //             继电器延时计数变量waittime<=1
 {
  
   DDRK=0X30;//打开继电器两路输出电源 0X30 十六进制转二进制为 0011 0000 ,k端口数据方向寄存器4和5号引脚为输出
     PORTK=0X20;    // 0x20十六进制转二进制为 0010 0000 k端口数据寄存器第5号引脚高电平 红灯亮
 }
   else //否则     即 继电器延时计数变量waittime>1 
   {
       DDRK=0X30;    //打开继电器输出两路电源    0X30 十六进制转二进制为 0011 0000 k端口数据方向寄存器4和5号引脚为输出
     PORTK=0X10; //  0x10十六进制转二进制为 0001 0000 k端口数据寄存器第4号引脚高电平 绿灯亮
   }
   
   
 if(waittime==2)     //  当继电器延时计数变量waittime=2时
 {
  waittime=0;//重新      赋值 继电器延时计数变量为下次使用
 }  
}


//****************矩阵键盘模块*********//
void juzhengjianpan(void)//无接收值的矩阵
{
                 DDRH_DDRH0=1;//接通行扫描线电源 H端口数据方向寄存器0号引脚为输出 
                        while(PTH_PTH4==0)//判断数据寄存器PH4引脚接受到按键按下的低电平信号
                         //默认输入  若加写DDRA=0;此按键屏蔽
                                PORTA_BIT7=0;//PA7引脚低电平通电
                                PORTA_BIT7=1;//PA7引脚高电平断电
                        while(PTH_PTH5==0)//判断数据寄存器PH5引脚接受到按键按下的低电平信号
                          //默认输入      若加写DDRA=0;此按键屏蔽
                                PORTA_BIT6=0;//PA6引脚低电平通电
                                PORTA_BIT6=1; //PA6 引脚高电平断电
                        while(PTH_PTH6==0)//判断数据寄存器PH6引脚接受到按键按下的低电平信号
                          //默认输入     若加写DDRA=0;此按键屏蔽
                                PORTA_BIT5=0; //PA5 引脚低电平通电
                                PORTA_BIT5=1;  //  PA5 引脚高电平断电
                        while(PTH_PTH7==0)//判断数据寄存器PH7引脚接受到按键按下的低电平信号
                          //默认输入    若加写DDRA=0;此按键屏蔽
                                PTM_PTM5=0;//PM5    引脚低电平通电
                                PTM_PTM5=1; //   PM5   引脚高电平断电
                 DDRH_DDRH0=0;
                 
                 
                 
                 
                 DDRH_DDRH1=1;
                        while(PTH_PTH4==0)
                                PORTA_BIT4=0;
                                PORTA_BIT4=1;
                        while(PTH_PTH5==0)
                                PORTA_BIT3=0;
                                PORTA_BIT3=1;
                        while(PTH_PTH6==0)
                                PORTA_BIT2=0;
                                PORTA_BIT2=1;
                        while(PTH_PTH7==0)
                                PORTA_BIT1=0;
                                PORTA_BIT1=1;
                 DDRH_DDRH1=0;
                 
                 
                 
                 
                 DDRH_DDRH2=1;
                        while(PTH_PTH4==0)
                               PTM_PTM7=0;
                               PTM_PTM7=1;
                        while(PTH_PTH5==0)
                               PORTB_BIT2=0;
                               PORTB_BIT2=1;
                        while(PTH_PTH6==0)
                               PORTB_BIT0=0;
                               PORTB_BIT0=1;
                        while(PTH_PTH7==0)
                               PTM_PTM6=0;
                               PTM_PTM6=1;
                 DDRH_DDRH2=0;
                 
                 
                 
                 
                 DDRH_DDRH3=1;
                        while(PTH_PTH4==0)
                               PORTK_BIT7=0;
                               PORTK_BIT7=1;
                        while(PTH_PTH5==0)
                               PORTE_BIT2=0;
                               PORTE_BIT2=1;
                        while(PTH_PTH6==0)
                               PORTE_BIT3=0;
                               PORTE_BIT3=1;
                        while(PTH_PTH7==0)
                               PTM_PTM4=0;
                               PTM_PTM4=1;
                 DDRH_DDRH3=0;                        
}


//*****************拨码开关模块***********//
void bomakaiguang(void)
{
   DDRJ_DDRJ1=0; // 1
   DDRJ_DDRJ0=0; // 2
   DDRB_BIT1=0;  // 3
   DDRB_BIT3=0;  // 4
/* DDRB_BIT4=0;  // 5    //此处拨码暂时无用
   DDRB_BIT5=0;  // 6
   DDRB_BIT6=0;  // 7
   DDRA_BIT0=0;  // 8
*/
    
   if(PTJ_PTJ1==1) //1号开关接通
   {
     jidianqi_star=1; 
   } 
     else 
     {
       jidianqi_star=0;     //定义继电器开关
     }
   
   
   
    if(PTJ_PTJ0==1) //2号开关接通
    {
      juzhengjianpan_star=1;
    } 
      else
      {
        juzhengjianpan_star=0;   //矩阵键盘开关打开
      }
     
     
     
     if(PORTB_BIT1==1)   //3号开关接通打开
    {
      paomadeng_star=1; 
    }
      else
      {
        paomadeng_star=0;       //跑马灯开关打开
      }
      
   
}


//*****************LED初始化*******************//
void LED_init()
{
  DDRA=0XFE;//转换为2进制1111 1110 打开7654321
  DDRB=0X05;       //转换为2进制 0101打开30
  DDRE=0X0C;      //转换为2进制     1100打开32
  DDRK=0X80;          //转换为2进制 1000 0000打开7
  DDRM=0XF0;         //转换为2进制   1111 0000打开7654
  PORTA=0XFE;         //转换为2进制  1111 1110 打开7654321
  PORTB=0X05;                      //转换为2进制   0101打开30
  PORTE=0X0C;                       //转换为2进制    1100打开32
  PORTK=0X80;       //转换为2进制                1000 0000打开7
  PTM=0XF0;          //转换为2进制 1111 0000打开7654
}

//*****************LED模块*************//
void paomadeng()
{

times++;           //时间累加依次按键

switch(times)//一对多选择time作为输入            注意!!!!低电平灯亮   高电平灯灭
{
  case 1:PORTA_BIT7=0;PORTE_BIT3=1;break;//time=1时,按下case 1按键执行PA7低电平灯亮,PE3高电平灯灭 break执行完后跳出
  case 2:PORTA_BIT6=0;PORTA_BIT7=1;break; // time=2时,按下case 2按键执行PA6低电平灯亮,PA7高电平灯灭
  case 3:PORTA_BIT5=0;PORTA_BIT6=1;break;
  case 4:PORTA_BIT4=0;PORTA_BIT5=1;break;
  case 5:PORTA_BIT3=0;PORTA_BIT4=1;break;
  case 6:PORTA_BIT2=0;PORTA_BIT3=1;break;
  case 7:PTIM=0X7F;PORTA_BIT2=1; break;    // 0x7f转换2进制为0111 1111 M端口6543210号高电平,PA2高电平灯灭
  case 8:PORTB_BIT2=0;PTM=0XFF; break;       // PB2低电平灯亮,0xff转换2进制为1111 1111 M端口76543210号高电平灯灭
  case 9:PORTB_BIT0=0;PORTB_BIT2=1;break;
  case 10:PORTK_BIT7=0;PORTB_BIT0=1;break;
  case 11:PORTE_BIT2=0;PORTK_BIT7=1; break;
  case 12:PORTE_BIT3=0;PORTE_BIT2=1; break;
  case 13:PTM=0XD0;PORTE_BIT3=1; break;   // 0xd0 转换2进制为 0110 1000 M端口653号高电平其余为低,PE3高电平灯灭
  case 14:PORTA_BIT1=0;PTM=0XFF; break;//PA1低电平灯亮 PTM 0xff  转换2进制为 1111 1111 M端口76543210号高电平
  case 15:PTM=0XB0;PORTA_BIT1=1; break;//PTM 0xb0 转换2进制为 1011 0000 M端口754高电平其余为低,PA1高电平
  case 16:PTM=0XE0;PTM=0XFF; break; // 0xe0 转换2进制为 1110 0000 M端口765高电平其余为低,0xff  转换2进制为 1111 1111 M端口76543210高电平
  case 17:PTM=0XFF;  break;     // 0xff    转换2进制为 1111 1111 M端口76543210高电平
  default:break;//跳出按键
}
delay(500);//调用延时函数传值 500
if(times==17)//如果 跑马灯依次按键计数变量time=17 
times=0;//重新赋值为0 为下次使用

}


//**************主函数*****************//
void main(void) 
{
 
   LED_init(); //LED灯初始化
  for(;;)
  {
     bomakaiguang();  //拨码开关
    if(jidianqi_star==1) //如果继电器通电
    {
      jidianqi();  //继电器
    }
     
    if(juzhengjianpan_star==1) 
    {
      juzhengjianpan(); //矩阵键盘
    }
   
    if(paomadeng_star==1)
    {
      paomadeng();  //跑马灯
    }
  } 
  
}

 

//*******************************************////***         演示程序一                  ***//// ******************************************//
//*******************************************// //*描述:                                   *////*   此程序包含以下几个模块:              *////*    交通灯、矩阵键盘、继电器、拨码开关   *////*                                         *////*  目的:                                 *////*    完成简单的I/O控制,熟悉基本C语言编程 *////*******************************************//

//用拨码开关来控制模块的调用//#include <hidef.h>      /* common defines and macros */#include "derivative.h"      /* derivative-specific definitions */
////////////////////////////////////////////
//全局变量的定义unsigned int waittime=0;//定义继电器延时计数变量unsigned int jidianqi_star=0;//定义继电器开关unsigned int juzhengjianpan_star=0; //矩阵键盘开关unsigned int paomadeng_star=0;       //跑马灯开关unsigned int times=0;//跑马灯依次按键计数变量 //*************延时********************//void delay(unsigned int num) //接收无符号延时变量 num{                                                     int i;                   //定义延时变量 i //2重循环 for(num;num>0;num--)                     //num循环减1 {                                                     for(i=100;i>=0;i--);                      //在num循环减1内依次i循环减1 }}

//****************继电器模块***********//void jidianqi(void) //无接收值继电器{delay(2000);//定义             num=2000并调用延时函数   waittime++;    //             继电器延时计数变量waittime+1 if(waittime<=1)    //             继电器延时计数变量waittime<=1 {     DDRK=0X30;//打开继电器两路输出电源 0X30 十六进制转二进制为 0011 0000 ,k端口数据方向寄存器4和5号引脚为输出     PORTK=0X20;    // 0x20十六进制转二进制为 0010 0000 k端口数据寄存器第5号引脚高电平 红灯亮 }   else //否则     即 继电器延时计数变量waittime>1    {       DDRK=0X30;    //打开继电器输出两路电源    0X30 十六进制转二进制为 0011 0000 k端口数据方向寄存器4和5号引脚为输出     PORTK=0X10; //  0x10十六进制转二进制为 0001 0000 k端口数据寄存器第4号引脚高电平 绿灯亮   }       if(waittime==2)     //  当继电器延时计数变量waittime=2时 {  waittime=0;//重新      赋值 继电器延时计数变量为下次使用 }  }

//****************矩阵键盘模块*********//void juzhengjianpan(void)//无接收值的矩阵{                 DDRH_DDRH0=1;//接通行扫描线电源 H端口数据方向寄存器0号引脚为输出                         while(PTH_PTH4==0)//判断数据寄存器PH4引脚接受到按键按下的低电平信号                         //默认输入  若加写DDRA=0;此按键屏蔽                                PORTA_BIT7=0;//PA7引脚低电平通电                                PORTA_BIT7=1;//PA7引脚高电平断电                        while(PTH_PTH5==0)//判断数据寄存器PH5引脚接受到按键按下的低电平信号                          //默认输入      若加写DDRA=0;此按键屏蔽                                PORTA_BIT6=0;//PA6引脚低电平通电                                PORTA_BIT6=1; //PA6 引脚高电平断电                        while(PTH_PTH6==0)//判断数据寄存器PH6引脚接受到按键按下的低电平信号                          //默认输入     若加写DDRA=0;此按键屏蔽                                PORTA_BIT5=0; //PA5 引脚低电平通电                                PORTA_BIT5=1;  //  PA5 引脚高电平断电                        while(PTH_PTH7==0)//判断数据寄存器PH7引脚接受到按键按下的低电平信号                          //默认输入    若加写DDRA=0;此按键屏蔽                                PTM_PTM5=0;//PM5    引脚低电平通电                                PTM_PTM5=1; //   PM5   引脚高电平断电                 DDRH_DDRH0=0;                                                                                     DDRH_DDRH1=1;                        while(PTH_PTH4==0)                                PORTA_BIT4=0;                                PORTA_BIT4=1;                        while(PTH_PTH5==0)                                PORTA_BIT3=0;                                PORTA_BIT3=1;                        while(PTH_PTH6==0)                                PORTA_BIT2=0;                                PORTA_BIT2=1;                        while(PTH_PTH7==0)                                PORTA_BIT1=0;                                PORTA_BIT1=1;                 DDRH_DDRH1=0;                                                                                     DDRH_DDRH2=1;                        while(PTH_PTH4==0)                               PTM_PTM7=0;                               PTM_PTM7=1;                        while(PTH_PTH5==0)                               PORTB_BIT2=0;                               PORTB_BIT2=1;                        while(PTH_PTH6==0)                               PORTB_BIT0=0;                               PORTB_BIT0=1;                        while(PTH_PTH7==0)                               PTM_PTM6=0;                               PTM_PTM6=1;                 DDRH_DDRH2=0;                                                                                     DDRH_DDRH3=1;                        while(PTH_PTH4==0)                               PORTK_BIT7=0;                               PORTK_BIT7=1;                        while(PTH_PTH5==0)                               PORTE_BIT2=0;                               PORTE_BIT2=1;                        while(PTH_PTH6==0)                               PORTE_BIT3=0;                               PORTE_BIT3=1;                        while(PTH_PTH7==0)                               PTM_PTM4=0;                               PTM_PTM4=1;                 DDRH_DDRH3=0;                        }

//*****************拨码开关模块***********//void bomakaiguang(void){   DDRJ_DDRJ1=0; // 1   DDRJ_DDRJ0=0; // 2   DDRB_BIT1=0;  // 3   DDRB_BIT3=0;  // 4/* DDRB_BIT4=0;  // 5    //此处拨码暂时无用   DDRB_BIT5=0;  // 6   DDRB_BIT6=0;  // 7   DDRA_BIT0=0;  // 8*/       if(PTJ_PTJ1==1) //1号开关接通   {     jidianqi_star=1;    }      else      {       jidianqi_star=0;     //定义继电器开关     }             if(PTJ_PTJ0==1) //2号开关接通    {      juzhengjianpan_star=1;    }       else      {        juzhengjianpan_star=0;   //矩阵键盘开关打开      }                    if(PORTB_BIT1==1)   //3号开关接通打开    {      paomadeng_star=1;     }      else      {        paomadeng_star=0;       //跑马灯开关打开      }         }

//*****************LED初始化*******************//void LED_init(){  DDRA=0XFE;//转换为2进制1111 1110 打开7654321  DDRB=0X05;       //转换为2进制 0101打开30  DDRE=0X0C;      //转换为2进制     1100打开32  DDRK=0X80;          //转换为2进制 1000 0000打开7  DDRM=0XF0;         //转换为2进制   1111 0000打开7654  PORTA=0XFE;         //转换为2进制  1111 1110 打开7654321  PORTB=0X05;                      //转换为2进制   0101打开30  PORTE=0X0C;                       //转换为2进制    1100打开32  PORTK=0X80;       //转换为2进制                1000 0000打开7  PTM=0XF0;          //转换为2进制 1111 0000打开7654}
//*****************LED模块*************//void paomadeng(){
times++;           //时间累加依次按键
switch(times)//一对多选择time作为输入            注意!!!!低电平灯亮   高电平灯灭{  case 1:PORTA_BIT7=0;PORTE_BIT3=1;break;//time=1时,按下case 1按键执行PA7低电平灯亮,PE3高电平灯灭 break执行完后跳出  case 2:PORTA_BIT6=0;PORTA_BIT7=1;break; // time=2时,按下case 2按键执行PA6低电平灯亮,PA7高电平灯灭  case 3:PORTA_BIT5=0;PORTA_BIT6=1;break;  case 4:PORTA_BIT4=0;PORTA_BIT5=1;break;  case 5:PORTA_BIT3=0;PORTA_BIT4=1;break;  case 6:PORTA_BIT2=0;PORTA_BIT3=1;break;  case 7:PTIM=0X7F;PORTA_BIT2=1; break;    // 0x7f转换2进制为0111 1111 M端口6543210号高电平,PA2高电平灯灭  case 8:PORTB_BIT2=0;PTM=0XFF; break;       // PB2低电平灯亮,0xff转换2进制为1111 1111 M端口76543210号高电平灯灭  case 9:PORTB_BIT0=0;PORTB_BIT2=1;break;  case 10:PORTK_BIT7=0;PORTB_BIT0=1;break;  case 11:PORTE_BIT2=0;PORTK_BIT7=1; break;  case 12:PORTE_BIT3=0;PORTE_BIT2=1; break;  case 13:PTM=0XD0;PORTE_BIT3=1; break;   // 0xd0 转换2进制为 0110 1000 M端口653号高电平其余为低,PE3高电平灯灭  case 14:PORTA_BIT1=0;PTM=0XFF; break;//PA1低电平灯亮 PTM 0xff  转换2进制为 1111 1111 M端口76543210号高电平  case 15:PTM=0XB0;PORTA_BIT1=1; break;//PTM 0xb0 转换2进制为 1011 0000 M端口754高电平其余为低,PA1高电平  case 16:PTM=0XE0;PTM=0XFF; break; // 0xe0 转换2进制为 1110 0000 M端口765高电平其余为低,0xff  转换2进制为 1111 1111 M端口76543210高电平  case 17:PTM=0XFF;  break;     // 0xff    转换2进制为 1111 1111 M端口76543210高电平  default:break;//跳出按键}delay(500);//调用延时函数传值 500if(times==17)//如果 跑马灯依次按键计数变量time=17 times=0;//重新赋值为0 为下次使用
}

//**************主函数*****************//void main(void) {    LED_init(); //LED灯初始化  for(;;)  {     bomakaiguang();  //拨码开关    if(jidianqi_star==1) //如果继电器通电    {      jidianqi();  //继电器    }         if(juzhengjianpan_star==1)     {      juzhengjianpan(); //矩阵键盘    }       if(paomadeng_star==1)    {      paomadeng();  //跑马灯    }  }   }

猜你喜欢

转载自www.cnblogs.com/WangYiqiang/p/9690035.html