搜索
bottom↓
回复: 10

【征文活动】基于KL25芯片 飞思卡尔芯片 使用心得

[复制链接]

出0入0汤圆

发表于 2015-3-1 17:32:13 | 显示全部楼层 |阅读模式
【背景】参与论坛的 《飞思卡尔KL25开源项目》
有幸参与了论坛的飞思卡尔KL25开源活动,http://www.amobbs.com/thread-5610374-1-1.html 开始真正接触到飞思卡尔的芯片。
下边这是苏州大学的板子,相信好些参与活动的人都有。


以前上家公司也用过飞思卡尔的芯片 MC90S 系列的,当时的印象是一个字贵,两个字高大,三个字就是高大上了,呵呵。当时看了下该芯片的环境是专用的,仿真器也是专用的。在AVR盛行的时候,个人感觉个人玩的话玩不起来。
刚好有这次征文活动,把我接触到飞思卡尔芯片以来,以一个飞思卡尔新手来说说芯片的使用感觉说一下,顺便说说我的入门经历和使用心得。
参加活动时候特意搜了下,基于MDK的环境的例程相对较少。心里有点悬。后来开发板收到了,看了下配套的书,大概翻了下基本资源的简介,心里有底了。
GPIO的配置,串口,SPI的配置,相对比较简单。跟STM32一大串关键字定义的库函数相比,可以理解为飞思卡尔的芯片的寄存器配置,就是稍微复杂的51单片机。
赶快到网上找例程,找DEMO程序。找到了一个点灯的。挡下来,看了下  MKL25Z4.h 的寄存器定义,关键字定义。对照书上发现不怎么对劲,举个例子 MDK例程 是 SIM->SCGC4 ,结果书上配套是 SIM_SCGC4。。。等等一些不太一样。
好在字符都是一样的。就是要动手修改。
慢慢的,熟悉了寄存器操作和 MKL25Z4.h 的定义 一切都变得简单了。
先写到这里,后边楼层会 谈谈,基于MDK的 飞思卡尔 KL25 的一些 模块的使用。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2015-3-2 11:33:06 | 显示全部楼层
期待楼主更多心得分享哦!

出0入0汤圆

 楼主| 发表于 2015-3-2 18:02:17 | 显示全部楼层
下边谈谈GPIO的基本控制。
1:SIM_SCGC5 寄存器。使能GPIO的时钟的。下边是mkl25z.h关于SIM_SCGC5的基本定义。
/* SCGC5 Bit Fields */
#define SIM_SCGC5_LPTMR_MASK                     0x1u
#define SIM_SCGC5_LPTMR_SHIFT                    0
#define SIM_SCGC5_TSI_MASK                       0x20u
#define SIM_SCGC5_TSI_SHIFT                      5
#define SIM_SCGC5_PORTA_MASK                     0x200u
#define SIM_SCGC5_PORTA_SHIFT                    9
#define SIM_SCGC5_PORTB_MASK                     0x400u
#define SIM_SCGC5_PORTB_SHIFT                    10
#define SIM_SCGC5_PORTC_MASK                     0x800u
#define SIM_SCGC5_PORTC_SHIFT                    11
#define SIM_SCGC5_PORTD_MASK                     0x1000u
#define SIM_SCGC5_PORTD_SHIFT                    12
#define SIM_SCGC5_PORTE_MASK                     0x2000u
#define SIM_SCGC5_PORTE_SHIFT                    13
在GPIO口初始化配置前先要是能 相应的 位。
SIM->SCGC5    |= (SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK );      /* Enable Clock to Port A - E */
上边这个例子就是 使能 PORTA PORTB PORTC PORTD PORTE  的时钟。
其次就是配置引脚功能复用配置。
下边这个是 mkl25z.h 里对于 GPIO的结构体定义。
typedef struct {
  __IO uint32_t PCR[32];                           /**< Pin Control Register n, array offset: 0x0, array step: 0x4 */
  __O  uint32_t GPCLR;                             /**< Global Pin Control Low Register, offset: 0x80 */
  __O  uint32_t GPCHR;                             /**< Global Pin Control High Register, offset: 0x84 */
       uint8_t RESERVED_0[24];
  __IO uint32_t ISFR;                              /**< Interrupt Status Flag Register, offset: 0xA0 */
} PORT_Type;

下边是 每一组IO的 地址定义
/** Peripheral PORTA base address */
#define PORTA_BASE                               (0x40049000u)
/** Peripheral PORTA base pointer */
#define PORTA                                    ((PORT_Type *)PORTA_BASE)
/** Peripheral PORTB base address */
#define PORTB_BASE                               (0x4004A000u)
/** Peripheral PORTB base pointer */
#define PORTB                                    ((PORT_Type *)PORTB_BASE)
/** Peripheral PORTC base address */
#define PORTC_BASE                               (0x4004B000u)
/** Peripheral PORTC base pointer */
#define PORTC                                    ((PORT_Type *)PORTC_BASE)
/** Peripheral PORTD base address */
#define PORTD_BASE                               (0x4004C000u)
/** Peripheral PORTD base pointer */
#define PORTD                                    ((PORT_Type *)PORTD_BASE)
/** Peripheral PORTE base address */
#define PORTE_BASE                               (0x4004D000u)
/** Peripheral PORTE base pointer */
#define PORTE                                    ((PORT_Type *)PORTE_BASE)
/** Array initializer of PORT peripheral base pointers */
#define PORT_BASES                               { PORTA, PORTB, PORTC, PORTD, PORTE }

例如想设置PORTB的第1位(PB0,PB1)为输出可以这样写。

1:首先选择 引脚复用为基本GPIO。
PORTB->PCR[0]  = PORT_PCR_MUX(1);
PORTB->PCR[1]  = PORT_PCR_MUX(1);
PORTB  上边已经又定义了。PCR 每一组(PORTA,PORTB......)的每一个管脚都有一个 PCR寄存器。
为什么要 PORT_PCR_MUX(1)  
下边是 mkl25z.h 对于 PORT_PCR_MUX 的定义。
#define PORT_PCR_MUX(x)                          (((uint32_t)(((uint32_t)(x))<<PORT_PCR_MUX_SHIFT))&PORT_PCR_MUX_MASK)
参考手册
PORTB 的第0个管脚 ALT0 : ADC0SE8    ALT1: PTB0    ALT2:IIC0_SCL      ALT3 :TPM1_CH0 ;
PORTB 的第1个管脚 ALT0 : ADC0SE9    ALT1: PTB1    ALT2:IIC0_SDA     ALT3 :TPM1_CH1 ;
想使用什么功能,就PORT_PCR_MUX(n)。
我们要的是输出,属于PTBn功能。我们就 PORT_PCR_MUX(1);
2:下边开始配置引脚功能的输入输出。
这是 mkl25z.h 对于引脚控制配置的结构体定义。
/** FGPIO - Register Layout Typedef */
typedef struct {
  __IO uint32_t PDOR;                              /**< IO数据输出寄存器 */
  __O  uint32_t PSOR;                              /**< IO数据置一寄存器 */
  __O  uint32_t PCOR;                              /**< IO数据清零寄存器 */
  __O  uint32_t PTOR;                              /**< IO数据翻转寄存器 */
  __I  uint32_t PDIR;                                /**< IO数据输入寄存器 */
  __IO uint32_t PDDR;                              /**< IO引脚方向寄存器 */
} FGPIO_Type;

FPTB->PDDR |= (1UL<<0)|(1UL<<1);                   /* enable PTB0/1 as Output */
PDDR 是引脚输入输出控制寄存器 ,是一个32位宽的寄存器。 从低位开始 每一个bit 对应一个 引脚。 (bit0 -》PTB0 ,bit1-》PTB1..........)如果某BIT 为1 则相应的 PTBn 为输出。 为0 则为输入。芯片复位默认的是 0,即为输入。
现在引脚功能已经基本配置玩了。
3:在电路中我们可能还要设置 默认输出电平。PODR 为输出电平控制,芯片复位上电是0所以输出是0,如果我们想输出是1则可以按下边的方法操作。
FPTB->PODR |= (1UL<<0)|(1UL<<1);                  
设置 PTB0,PTB1 输出 高电平。
至此 我们引脚的功能配置就完成了。

下边再说说引脚的基本控制
PSOR 某1BIT为1 则输出引脚 会输出1.PDOR的相应BIT也会为1.
PCOR  某1BIT为1 则输出引脚 会输出0.PDOR的相应BIT也会为0.
PTOR 某1BIT为1 则输出引脚 会翻转电平,即原来为0,现在为1。
下边是我们对于输出高低电平的定义

#define PTB0L        FPTB->PCOR   |= 1UL << 0;         
#define PTB0H   FPTB->PSOR   |= 1UL << 0;

#define PTB1L        FPTB->PCOR   |= 1UL << 1;         
#define PTB1H   FPTB->PSOR   |= 1UL << 1;

.如果将引脚配置为输入的话,PD0R 的值决定了是否上拉。
读输入口状态的话
#define PTB0IN  FPTB->PDIR &(1UL<<0)
#define PTB1IN  FPTB->PDIR &(1UL<<1)






出0入0汤圆

 楼主| 发表于 2015-3-2 18:12:39 | 显示全部楼层
  PDOR;                              /**< IO数据输出寄存器 */
  PSOR;                              /**< IO数据置一寄存器 */
  PCOR;                              /**< IO数据清零寄存器 */
  PTOR;                              /**< IO数据翻转寄存器 */
  PDIR;                                /**< IO数据输入寄存器 */
  PDDR;                              /**< IO引脚方向寄存器 */
有人要问了,这么多寄存器不麻烦么。
这对于位操作相当方便啊。
输出0 直接对PCOR 相应的BIT操作,不用考虑其他的BIT.
输出1 直接对PSOR 相应的BIT操作,不用考虑其他的BIT.
要想翻转某个位 直接对 PTOR相应的BIT 操作。省的读取在判断再写入。

出0入0汤圆

发表于 2015-3-5 12:22:22 | 显示全部楼层
直接操作寄存器确实麻烦,还好有周立功的例程可以参考

出0入0汤圆

 楼主| 发表于 2015-3-5 16:30:06 | 显示全部楼层
duhui75 发表于 2015-3-5 12:22
直接操作寄存器确实麻烦,还好有周立功的例程可以参考

我比较喜欢对寄存器操作,最起码程序大概是什么样。自己心里有数。。呵呵

出0入0汤圆

发表于 2015-3-6 10:44:50 | 显示全部楼层
XUEPENGBIN 发表于 2015-3-5 16:30
我比较喜欢对寄存器操作,最起码程序大概是什么样。自己心里有数。。呵呵 ...

那得操作到猴年马月啊 工作是讲究效率的

出0入0汤圆

发表于 2015-3-6 11:03:53 | 显示全部楼层
XUEPENGBIN 发表于 2015-3-2 18:02
下边谈谈GPIO的基本控制。
1:SIM_SCGC5 寄存器。使能GPIO的时钟的。下边是mkl25z.h关于SIM_SCGC5的基本定 ...

楼主你的这个帖子很好,虽然我看了一遍没怎么明白,我再多看几遍。32位和原来16位的真是相差太大了。我那个ke02的板子我就新建了个工程,结果我倒ke02头文件里面看是什么也看不懂。你这个帖子说的不错!谢谢分享!

出0入0汤圆

 楼主| 发表于 2015-3-6 11:14:39 | 显示全部楼层
duhui75 发表于 2015-3-6 10:44
那得操作到猴年马月啊 工作是讲究效率的

没有啊。寄存器也没多少。都是比较简单的拉。。个人感觉,相比STM32来说。飞思卡尔的寄存器配置很简单。下一篇,写写,USART。。。最近有点忙。。

出0入0汤圆

 楼主| 发表于 2015-3-6 11:24:46 | 显示全部楼层
jiang887786 发表于 2015-3-6 11:03
楼主你的这个帖子很好,虽然我看了一遍没怎么明白,我再多看几遍。32位和原来16位的真是相差太大了。我那 ...

可能我的表达不是很清楚。给个完整的例子你就明白了。

void LCD_Gpio_Config(void)
         {

      SIM->SCGC5    |=(SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK );       //使能时钟A------E
//配置PD0---PD7 为普通IO;                  
      PORTD->PCR[0]  = PORT_PCR_MUX(1);                     
      PORTD->PCR[1]  = PORT_PCR_MUX(1);                     
      PORTD->PCR[2]  = PORT_PCR_MUX(1);                       
      PORTD->PCR[3]  = PORT_PCR_MUX(1);               
      PORTD->PCR[4]  = PORT_PCR_MUX(1);                       
      PORTD->PCR[5]  = PORT_PCR_MUX(1);                     
      PORTD->PCR[6]  = PORT_PCR_MUX(1);               
      PORTD->PCR[7]  = PORT_PCR_MUX(1);     
//设置输出高电平                  
      FPTD->PDOR = 0XFF;  
//设置管脚为输出                                    
      FPTD->PDDR = 0XFF;                                                             
   }       
管脚初始化就好了。
下边是预定义
#define CSRC522L  FPTD->PCOR   |= 1UL << 0
#define CSRC522H  FPTD->PSOR   |= 1UL << 0


int main (void)
{
CSRC522L  ;
.
.
.
CSRC522H  ;
.

.
}

出0入0汤圆

 楼主| 发表于 2015-3-13 10:57:10 | 显示全部楼层
飞思卡尔串口的使用。。。

#define UART_PARAM_DEBUG        0                                                       /* 是否进行参数检查     */
#define UART_PARAM_PORTNUM(x)   (x > 3? 1 : 0)                                  /* 端口号检查           */
#define UART_PARAM_MODE(x)      (x > 3? 1 : 0)                                     /* 模式检查             */
#define UART_PARAM_LENGTH(x)    ((x == 8)||(x == 9)||(x == 9) ? 1 : 0)          /* 数据长度检查         */
#define UART_PARAM_STOP(x)      ((x == 1)||(x == 2)? 1 : 0)                           /* 停止位检查           */
#define UART_PARAM_PARITY(x)    ((x == 0)||(x == 1)? 1 : 0)                          /* 校验位检查           */
#define UART_PARAM_LOGIC(x)     ((x == 0)||(x == 1)? 1 : 0)                          /* 逻辑位检查           */
#define UART_CHECK_PARAM(x)     (x? (while (1)):)                                          /* 错误处理             */

#define UART0_DEFAULT_OPEN      1                                               /* 是否默认打开传输          */                                
#define UART0_IRQ_ENABLE        1                                                 /* 串口中断允许          */   

#define UART1_DEFAULT_OPEN      1                                              /* 是否默认打开传输          */                              
#define UART1_IRQ_ENABLE        1                                                 /* 串口中断允许          */

串口1和串口2 是基本相同,把串口1分析一下。
void uart1Init( uint32_t  ulBaudRate,
                uint8_t   ucParityEnable,
                uint8_t   ucParityType,
                uint8_t   ucDataLength,
                uint8_t   ucStopBit)
{
    register uint16_t usBaudRate  = 0;  

#if UART_PARAM_DEBUG
    UART_CHECK_PARAM(UART_PARAM_LENGTH(ucDataLength));
    UART_CHECK_PARAM(UART_PARAM_STOP(ucStopBit));
    UART_CHECK_PARAM(UART_PARAM_LOGIC(ucParityEnable));
    UART_CHECK_PARAM(UART_PARAM_PARITY(ucParityType));   
#endif  
   
    SIM->SCGC4 |= SIM_SCGC4_UART1_MASK;                                          /* 允许外设时钟         */      
    uart1TranControl(UART_TX_DISABLE, UART_RX_DISABLE);                         /* 首先禁止通信         */

// 配置串口使用的引脚;
    PORTC->PCR[3] = PORT_PCR_MUX(0x3);                                            /* UART0_TXD            */
    PORTC->PCR[4] = PORT_PCR_MUX(0x3);                                            /* UART0_RXD            */
// 有485的话,配置485的控制引脚       
    PORTC->PCR[2] = PORT_PCR_MUX(0x1);   
    FPTC->PDOR |=  (1UL<<2);
    FPTC->PDDR |=  (1UL<<2);
//485控制引脚配置结束       
    UART1->C1  &= ~(UART_C1_M_MASK |  UART_C1_PT_MASK |  UART_C1_PE_MASK);  /* 数据长度             */
                                                                            /* 校验位类型           */
                                                                            /* 校验位               */
   
    UART1->C1  |= ((ucDataLength - 8UL) << UART_C1_M_SHIFT)|
                            (ucParityEnable << UART_C1_PE_SHIFT)|
                            (ucParityType << UART_C1_PT_SHIFT);               

   
    usBaudRate = SystemBusClock/(ulBaudRate * 16);  
               
    UART1->BDH   =  (usBaudRate & 0x1F00) >> 8;                         /* 波特率               */
    UART1->BDL   =  (uint8_t)(usBaudRate & UART_BDL_SBR_MASK);
    UART1->BDH  &= ~UART_BDH_SBNS_MASK;                                 /* 停止位               */
    UART1->BDH  |=  (ucStopBit - 1) << UART_BDH_SBNS_SHIFT;
               
    UART1->C2   &= ~(UART_C2_TIE_MASK  |
                           UART_C2_TCIE_MASK |
                                                                                 UART_C2_RIE_MASK  |
                                                                                 UART_C2_ILIE_MASK);                                /* 清除中断设置         */
                                

    while((UART1->S1  & UART_S1_RDRF_MASK) && (UART1->D));                                               /* 清接收缓冲区         */
   
    #if UART1_DEFAULT_OPEN   
    uart1TranControl(UART_TX_ENABLE, UART_RX_ENABLE);                           /* 配置完成允许通信     */
    #endif

    #if UART1_IRQ_ENABLE        
        #if UART1_SEND_IRQ
        UART1->C2  |= UART_C2_TCIE_MASK;
        #endif
        #if UART1_RECEIVE_IRQ
        UART1->C2   |= UART_C2_RIE_MASK;
        #endif                  
    NVIC_EnableIRQ(UART1_IRQn);                        
    #endif            
}
//串口传输控制。
void uart1TranControl(uint8_t ucTxEnable,
                      uint8_t ucRxEnable)
{
     
#if UART_PARAM_DEBUG
    UART_CHECK_PARAM(UART_PARAM_LOGIC(ucTxEnable));
    UART_CHECK_PARAM(UART_PARAM_LOGIC(ucRxEnable));
#endif   

    UART1->C2  &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK);
    UART1->C2  |= (ucTxEnable << UART_C2_TE_SHIFT)| (ucRxEnable << UART_C2_RE_SHIFT);
   
}
如果使能中断了下边是串口中断服务程序
由于串口的中断包括发送和接收中断。在此根据标记位来区分;


UART0_S1_RDRF_MASK  串口接收到有效数据
UART0_S1_TDRE_MASK  串口发送寄存器空
UART0_C2_TIE_MASK    串口发送中断使能位

void UART0_IRQHandler(void)
{   
   __disable_irq();   
   #if UART0_SEND_IRQ
                                                                               /* 发送中断处理程序     */
   while((UART0->S1  & UART0_S1_TDRE_MASK)&&(UART0->C2 & UART0_C2_TIE_MASK))
          {  
                                        (用户的发送中断处理函数);
        }                                                                                     
   #endif
   #if UART0_RECEIVE_IRQ
   while(UART0->S1  & UART0_S1_RDRF_MASK)
                    {  
                                        (用户的接收中断处理函数)
                     }                         
   #endif
          __enable_irq();                               
}

在用户写发送程序时 根据发送的数据缓冲来判断发送数据是否是最后一个字节,是的话,要及时清除掉 UART0_C2_TIE_MASK 这样就可以自由控制串口串口发送中断。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-21 14:09

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表