搜索

tag 标签: 寄存器

相关帖子

版块 作者 回复/查看 最后发表
STM32 RTC寄存器 【stm32/stm8】 bigbat 2020-2-12 8 333 threetigher 2020-2-15 12:18
【转】FPGA寄存器自动化配置核心设计技巧 FPGA/CPLD njiggih 2018-9-5 0 1111 njiggih 2018-9-5 10:26
MSP430单片机学习小记--基础定时器 【微控制器 MCU】 fish001 2017-6-25 0 707 fish001 2017-6-25 09:56
单片机 单片机 菲利盟电子 2017-6-8 0 1919 菲利盟电子 2017-6-8 11:17
ST加速度计使用基础篇 二 --Free fall, wake up, 6D功能【ST工程师文章系列】 attach_img ST传感器与低功耗无线技术论坛 nmg 2017-5-25 1 2059 dcexpert 2017-5-25 15:27
悬赏 MSP430F1232不能设置断点,寄存器写入失败,我打赌你们都没遇到过这种问题... - [悬赏 1 分芯积分] attach_img 【微控制器 MCU】 飞过漠北的蓝天 2017-5-25 6 2174 strong161 2017-5-26 10:18
MSP430寄存器的一些注释带中文解释 【微控制器 MCU】 Jacktang 2017-5-24 0 606 Jacktang 2017-5-24 15:24
MSP430学习经典方法 【微控制器 MCU】 Aguilera 2017-5-23 0 4747 Aguilera 2017-5-23 08:29
关于lsm6dsl状态寄存器的问题 MEMS传感器 wuhen123 2017-5-17 6 1593 zf1995 2018-4-17 17:53
帮忙看一下stm32的PWM输出,为什么我用示波器在PA7口测的只有高电平输出,没有波形 【stm32/stm8】 光林火叶 2017-4-27 3 3362 柠檬酸钠 2017-5-2 14:08
MSP430 单片机中断嵌套使用过程的总结 【微控制器 MCU】 fish001 2017-4-26 0 1313 fish001 2017-4-26 22:04
TMS320F28035学习记录 【微控制器 MCU】 Jacktang 2017-4-26 0 505 Jacktang 2017-4-26 21:53
I2C寄存器方式,每条代码都有注释。并且配上库操作作对比,希望给正在学习的人有帮助 attachment 【stm32/stm8】 赵怡彬 2017-4-24 8 2081 在学习的路上 2017-12-31 15:32
STM8L的CFG_GCR寄存器中AL要置1如何实现? attach_img 【stm32/stm8】 jiyiche 2017-4-23 9 2839 jiyiche 2017-5-8 08:39
stm32高级定时器主输出使能后,usart1就不能发送只能接收了? attachment 【stm32/stm8】 赵怡彬 2017-4-23 9 4686 wjcjm 2019-7-16 11:36
诚信做台湾麦肯单片机销售及方案开发 信息发布 hanlie2345678 2017-4-21 0 909 hanlie2345678 2017-4-21 17:25
数字电路设计方法 FPGA/CPLD inoint98 2017-4-19 0 1212 inoint98 2017-4-19 15:46
悬赏 MPU6050的0x75寄存器读出的数据问题 - [悬赏 1 分芯积分] 【stm32/stm8】 byl 2017-4-18 2 2646 byl 2017-4-18 17:29
MSP430寄存器中文注释 attach_img 【微控制器 MCU】 fish001 2017-5-22 0 404 fish001 2017-5-22 20:12
MSP432 spi接收中断寄存器问题 attach_img 【微控制器 MCU】 被雨困住 2017-6-13 9 2729 LZTT62 2017-6-22 19:31

相关日志

分享 寄存器理解
kingdomlzq 2018-7-31 21:44
1.寻址空间:STM32F429有4G寻址空间,表示其最多有4G个32位的可寻址空间。这里的寻址空间,可以理解为每个寻址空间对应一唯一个32位的存储单元 2.存储单元映射---寻址空间和存储单元一一对应 3.寄存器---特殊功能存储单元的别名。即寄存器的本质还是存储单元 4.寄存器通过头文件宏定义来实现,例如:#define GPIOH_ODR *(unsigned int*)(0x4002 1C14) 表示地址为(0x4002 1C14)的存储单元,其中 (unsigned int*)(0x4002 1C14) 表示0x4002 1C14是一个32位的地址指针,指针指向0x4002 1C14地址,*(unsigned int*)(0x4002 1C14)表示(0x4002 1C14)地址内存单元的内容。这种方式在单片机等底层文件普遍采用 5.更通用的寄存器访问,是通过结构体来实现的,把一定功能的寄存器统一定义为一个结构体,然后对结构体基址幅值为特定功能寄存器组的基址,举例如下: /* GPIO 寄存器列表 *///定义结构体GPIO列表GPIO_TypeDef typedef struct { uint32_t MODER; /*GPIO 模式寄存器 地址偏移: 0x00 */ uint32_t OTYPER; /*GPIO 输出类型寄存器 地址偏移: 0x04 */ uint32_t OSPEEDR; /*GPIO 输出速度寄存器 地址偏移: 0x08 */ uint32_t PUPDR; /*GPIO 上拉/下拉寄存器 地址偏移: 0x0C */ uint32_t IDR; /*GPIO 输入数据寄存器 地址偏移: 0x10 */ uint32_t ODR; /*GPIO 输出数据寄存器 地址偏移: 0x14 */ uint16_t BSRRL; /*GPIO 置位/复位寄存器低16 位部分 地址偏移: 0x18 */ uint16_t BSRRH; /*GPIO 置位/复位寄存器高16 位部分 地址偏移: 0x1A */ uint32_t LCKR; /*GPIO 配置锁定寄存器 地址偏移: 0x1C */ uint32_t AFR ; /*GPIO 复用功能配置寄存器 地址偏移: 0x20-0x24 */ } GPIO_TypeDef; GPIO_TypeDef * GPIOx; //定义一个GPIO_TypeDef 型结构体指针GPIOx GPIOx = GPIOH_BASE; //把指针地址设置为宏GPIOH_BASE 地址 然后接下来就可以通过结构体GPIOx来访问结构体内的寄存器了 GPIOx-BSRRL = 0xFFFF; 更直接的办法:使用宏定义 GPIO_TypeDef 把地址强制转换成指针 /*使用GPIO_TypeDef 把地址强制转换成指针*/ #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) #define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
个人分类: STM32学习笔记|771 次阅读|0 个评论
分享 寄存器理解
kingdomlzq 2018-7-31 21:44
1.寻址空间:STM32F429有4G寻址空间,表示其最多有4G个32位的可寻址空间。这里的寻址空间,可以理解为每个寻址空间对应一唯一个32位的存储单元 2.存储单元映射---寻址空间和存储单元一一对应 3.寄存器---特殊功能存储单元的别名。即寄存器的本质还是存储单元 4.寄存器通过头文件宏定义来实现,例如:#define GPIOH_ODR *(unsigned int*)(0x4002 1C14) 表示地址为(0x4002 1C14)的存储单元,其中 (unsigned int*)(0x4002 1C14) 表示0x4002 1C14是一个32位的地址指针,指针指向0x4002 1C14地址,*(unsigned int*)(0x4002 1C14)表示(0x4002 1C14)地址内存单元的内容。这种方式在单片机等底层文件普遍采用 5.更通用的寄存器访问,是通过结构体来实现的,把一定功能的寄存器统一定义为一个结构体,然后对结构体基址幅值为特定功能寄存器组的基址,举例如下: /* GPIO 寄存器列表 *///定义结构体GPIO列表GPIO_TypeDef typedef struct { uint32_t MODER; /*GPIO 模式寄存器 地址偏移: 0x00 */ uint32_t OTYPER; /*GPIO 输出类型寄存器 地址偏移: 0x04 */ uint32_t OSPEEDR; /*GPIO 输出速度寄存器 地址偏移: 0x08 */ uint32_t PUPDR; /*GPIO 上拉/下拉寄存器 地址偏移: 0x0C */ uint32_t IDR; /*GPIO 输入数据寄存器 地址偏移: 0x10 */ uint32_t ODR; /*GPIO 输出数据寄存器 地址偏移: 0x14 */ uint16_t BSRRL; /*GPIO 置位/复位寄存器低16 位部分 地址偏移: 0x18 */ uint16_t BSRRH; /*GPIO 置位/复位寄存器高16 位部分 地址偏移: 0x1A */ uint32_t LCKR; /*GPIO 配置锁定寄存器 地址偏移: 0x1C */ uint32_t AFR ; /*GPIO 复用功能配置寄存器 地址偏移: 0x20-0x24 */ } GPIO_TypeDef; GPIO_TypeDef * GPIOx; //定义一个GPIO_TypeDef 型结构体指针GPIOx GPIOx = GPIOH_BASE; //把指针地址设置为宏GPIOH_BASE 地址 然后接下来就可以通过结构体GPIOx来访问结构体内的寄存器了 GPIOx-BSRRL = 0xFFFF;
个人分类: STM32学习笔记|0 个评论
分享 LMP91000芯片寄存器设置
crystal008 2015-3-27 13:49
LMP91000是一个可编程的模拟前端,用于微功率电化学传感器。该芯片很早就开始研究,中间由于其他事情耽搁,最近又拾起来啦,所以做的比较久远;不过还好最终还是完成啦。值得注意的是,该芯片的浓度数据不是通过IIC读取的,而是通过ADC口读取到的,和传感器数据采集有些类似;IIC只是用来设置LMP91000芯片中寄存器的数值。以下是LMP91000芯片的驱动代码。 1. LMPIIC.H #ifndef __LMPIIC_H #define __LMPIIC_H #include #include "stm32f10x_i2c.h" #include "delay.h" #include "public.h" /***************************************IO方向设置**********************************************/ #define LMP_SDA_IN(){GPIOB-CRH=0XFFFF0FFF;GPIOB-CRH|=812;} #define LMP_SDA_OUT() {GPIOB-CRH=0XFFFF0FFF;GPIOB-CRH|=212;} //1 - 10MHZ2 - 2MHZ3- 50MHZ /***************************************IO操作函数**********************************************/ #define LMP_IIC_REF_EN PBout(13) //REF_EN #define LMP_IIC_MENB PAout(12) //MENB #define LMP_IIC_SCL PBout(10) //SCL #define LMP_IIC_SDA PBout(11) //SDA #define LMP_READ_SDA PBin(11) //输入SDA #define LMP_WRITE_ADDE 0x90 //LMP地址+写操作 #define LMP_READ_ADDE 0x91 //LMP地址+读操作 #define LMP_REG1_ADDE 0x00 //LMP寄存器1地址0x00 #define LMP_REG2_ADDE 0x01 //LMP寄存器2地址0x01 #define LMP_REG3_ADDE 0x10 //LMP寄存器3地址0x10 #define LMP_REG4_ADDE 0x11 //LMP寄存器4地址0x11 #define LMP_REG5_ADDE 0x12 //LMP寄存器5地址0x12 #define LMP_REG2_UNLOCK 0x00 //LMP寄存器2中的数据0x00 #define LMP_REG2_LOCK 0x01 //LMP寄存器2中的数据0x01 #define LMP_REG3_DATA 0x0F //LMP寄存器3中的数据0x0E #define LMP_REG4_DATA 0xB0 //LMP寄存器4中的数据0xB0 #define LMP_REG5_DATA 0x07 //LMP寄存器5中的数据0x07/03 /*************************************IIC所有操作函数*******************************************/ void LMP_IIC_Init_Func(void); //初始化IIC的IO口 void LMP_IIC_Start(void); //发送IIC开始信号 void LMP_IIC_Stop(void); //发送IIC停止信号 u8 LMP_IIC_Wait_Ack(void); //IIC等待ACK信号 void LMP_IIC_Ack(void); //IIC发送ACK信号 void LMP_IIC_NAck(void); //IIC不发送ACK信号 void LMP_IIC_Send_Byte(u8 txd); //IIC发送一个字节 u8 LMP_IIC_Read_Byte(u8 ack); //IIC读取一个字节 void LMP_Init_Func(void); //ADS初始化函数 u16LMP_Read_Func(void); //ADS读取函数 #endif 2. LMPIIC.C /************************************************************************************************ ** 函数名称:LMP_IIC_Init_Func ** 输入参数:无 ** 输出参数:无 ** 功能描述:初始化IIC的IO口以及调用ADS初始化函数 ************************************************************************************************/ void LMP_IIC_Init_Func(void) { GPIO_InitTypeDef GPIO_InitStructure; //PB10--SCLPB11--SDAPB13--REF_EN(LMP91000使用外部供电,供电使能位;也可选择使用内部供电) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, GPIO_InitStructure); //PA12--MENB GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, GPIO_InitStructure); //PB1--LMP91000数据采集 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚 GPIO_Init(GPIOB, GPIO_InitStructure); LMP_IIC_REF_EN = 1; LMP_IIC_SCL=1; LMP_IIC_SDA=1; LMP_Init_Func(); } /************************************************************************************************ ** 函数名称:LMP_IIC_MENB ** 输入参数:无 ** 输出参数:无 ** 功能描述:产生IIC起始信号 ************************************************************************************************/ void LMP_IIC_Start(void) { LMP_IIC_MENB = 0;//MEBN拉低 delay_us(4); LMP_SDA_OUT(); //sda线输出 LMP_IIC_SDA=1; LMP_IIC_SCL=1; delay_us(4); LMP_IIC_SDA=0; //START:when CLK is high,DATA change form high to low delay_us(4); LMP_IIC_SCL=0; //钳住I2C总线,准备发送或接收数据 } /************************************************************************************************ ** 函数名称:LMP_IIC_Stop ** 输入参数:无 ** 输出参数:无 ** 功能描述:产生IIC停止信号 ************************************************************************************************/ void LMP_IIC_Stop(void) { LMP_SDA_OUT(); //sda线输出 LMP_IIC_SCL=0; delay_us(4); LMP_IIC_SDA=0; //STOP:when CLK is high DATA change form low to high delay_us(4); LMP_IIC_SCL=1; delay_us(4); LMP_IIC_SDA=1; //发送I2C总线结束信号 delay_us(4); LMP_IIC_MENB = 1;//MEBN拉高 } /************************************************************************************************ ** 函数名称:LMP_IIC_Wait_Ack ** 输入参数:无 ** 输出参数:返回值 1,接收应答失败 ** 0,接收应答成功 ** 功能描述:等待应答信号到来 ************************************************************************************************/ u8 LMP_IIC_Wait_Ack(void) { u8 ucErrTime=0; LMP_SDA_IN(); //SDA设置为输入 LMP_IIC_SDA=1; delay_us(1); LMP_IIC_SCL=1; delay_us(1); while(LMP_READ_SDA) { ucErrTime++; if(ucErrTime250) { LMP_IIC_Stop(); return 1; } } LMP_IIC_SCL=0;//时钟输出0 return 0; } /************************************************************************************************ ** 函数名称:LMP_IIC_Ack ** 输入参数:无 ** 输出参数:无 ** 功能描述:产生ACK应答 ************************************************************************************************/ void LMP_IIC_Ack(void) { LMP_IIC_SCL=0; LMP_SDA_OUT(); LMP_IIC_SDA=0; delay_us(2); LMP_IIC_SCL=1; delay_us(2); LMP_IIC_SCL=0; } /************************************************************************************************ ** 函数名称:LMP_IIC_NAck ** 输入参数:无 ** 输出参数:无 ** 功能描述:不产生ACK应答 ************************************************************************************************/ void LMP_IIC_NAck(void) { LMP_IIC_SCL=0; LMP_SDA_OUT(); LMP_IIC_SDA=1; delay_us(2); LMP_IIC_SCL=1; delay_us(2); LMP_IIC_SCL=0; } /************************************************************************************************ ** 函数名称:LMP_IIC_Send_Byte ** 输入参数:txd:发送数据 ** 输出参数:无 ** 功能描述:IIC发送一个字节。 ************************************************************************************************/ void LMP_IIC_Send_Byte(u8 txd) { u8 t; LMP_SDA_OUT(); LMP_IIC_SCL=0; //拉低时钟开始数据传输 for(t=0;t8;t++) { LMP_IIC_SDA=(txd0x80)7; txd=1; delay_us(2); //对LMP91000这三个延时都是必须的 LMP_IIC_SCL=1; delay_us(2); LMP_IIC_SCL=0; delay_us(2); } LMP_IIC_SDA = 0; } /************************************************************************************************ ** 函数名称:LMP_IIC_Read_Byte ** 输入参数:ack: = 1时,发送ACK ** = 0时,发送nACK ** 输出参数:返回读取IIC中的数据。 ** 功能描述:IIC读取一个字节。 ************************************************************************************************/ u8 LMP_IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; LMP_SDA_IN(); //SDA设置为输入 for(i=0;i8;i++ ) { LMP_IIC_SCL=0; delay_us(2); LMP_IIC_SCL=1; receive=1; if(LMP_READ_SDA) receive++; delay_us(1); } if (!ack) LMP_IIC_NAck();//发送nACK else LMP_IIC_Ack(); //发送ACK return receive; } /************************************************************************************************ ** 函数名称:LMP_Init_Func ** 输入参数:无 ** 输出参数:无 ** 功能描述:通过IIC初始化ADS设置寄存器的值 ************************************************************************************************/ void LMP_Init_Func(void) { LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_WRITE_ADDE); //发送LMP91000地址 LMP+写操作位90 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG2_ADDE); //发送寄存器地址2 01 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG2_UNLOCK); //发送寄存器地址2中需要写入的数据 LMP_IIC_Wait_Ack(); LMP_IIC_Stop(); delay_us(8); LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_WRITE_ADDE); //发送LMP91000地址 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG3_ADDE); //发送寄存器地址2 10 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG3_DATA); //发送寄存器地址2中需要写入的数据 LMP_IIC_Wait_Ack(); LMP_IIC_Stop(); delay_us(8); LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_WRITE_ADDE); //发送LMP91000地址 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG4_ADDE); //发送寄存器地址2 11 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG4_DATA); //发送寄存器地址2中需要写入的数据 LMP_IIC_Wait_Ack(); LMP_IIC_Stop(); delay_us(8); LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_WRITE_ADDE); //发送LMP91000地址 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG5_ADDE); //发送寄存器地址2 12 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG5_DATA); //发送寄存器地址2中需要写入的数据 LMP_IIC_Wait_Ack(); LMP_IIC_Stop(); delay_us(8); LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_WRITE_ADDE); //发送LMP91000地址 LMP+写操作位 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG2_ADDE); //发送寄存器地址2 01 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG2_LOCK); //发送寄存器地址2中需要写入的数据 LMP_IIC_Wait_Ack(); LMP_IIC_Stop(); //产生一个停止条件 delay_ms(10); } /************************************************************************************************ ** 函数名称:LMP_Read_Func ** 输入参数:无 ** 输出参数:返回读取的ADS中数据 ** 功能描述:通过IIC读取ADS数据寄存器的值 ************************************************************************************************/ u16 LMP_Read_Func(void) { unsigned charun8Date; un8Date = 0; LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_WRITE_ADDE); //发送LMP91000地址 LMP_IIC_Wait_Ack(); LMP_IIC_Send_Byte(LMP_REG3_ADDE); //发送寄存器地址00 LMP_IIC_Wait_Ack(); LMP_IIC_Stop(); LMP_IIC_Start(); LMP_IIC_Send_Byte(LMP_READ_ADDE); //发送LMP91000地址 LMP_IIC_Wait_Ack(); un8Date = LMP_IIC_Read_Byte(0); LMP_IIC_Stop(); //产生一个停止条件 return (un8Date); } 3. MAIN.C int main(void) { delay_init(24); //延时初始化函数 RCC_Configuration(); //始终初始化函数 IIC_Init_Func(); //IIC初始化函数 LMP_IIC_Init_Func(); while (1) { G_un16ADCValue4 = ADC_Average(G_un16ADC_ConValue,3); G_un16V4Value4= (unsigned int)((unsigned long)G_un16ADCValue4 * 2480/4096); G_un16LMPValue = LMP_Read_Func(); } }
768 次阅读|0 个评论
分享 sonix 2711 读取 TI 的bq27541数据
zhangkaiy1220 2014-12-10 13:58
前段时间用到 TI 的 bq27541 需要电量管理,用单片机读取芯片的寄存器,用的是 I2C 协议,终于做出来了,分享下过程。 首先试着写出 i2c 协议,网上比较多,大家可以下载并参考,然后在 24C02 试着读写下数据,是否正常。 其次, 通讯正常,试着写下命令字,进行读取数据,其中有个温度读取 单位 是 0.1K ,这是开尔文单位,需要转换。 最后在程序中每次通讯下,检查下总线是否忙,避免数据错误。
个人分类: 学习|488 次阅读|0 个评论
分享 《51单片机特殊功能寄存器》(就是头文件说明)
447176737 2014-11-11 23:09
就是 keil 软件 c 语言编程的 REG51.H /*-------------------------------------------------------------------------- REG51.H Headerfileforgeneric80C51and80C31microcontroller. Copyright(c)1988-2001KeilElektronikGmbHandKeilSoftware,Inc. Allrightsreserved. --------------------------------------------------------------------------*/ /*BYTERegister*/ sfrP0=0x80; sfrP1=0x90; sfrP2=0xA0; sfrP3=0xB0; sfrPSW=0xD0; 程序状态字 sfrACC=0xE0; 累加器 sfrB=0xF0;B 寄存器 sfrSP=0x81; 堆栈指针 sfrDPL=0x82; 数据指针低八位 sfrDPH=0x83; 数据指针高八位 sfrPCON=0x87; 波特率选择寄存器 sfrTCON=0x88; 定时器 / 计数器控制寄存器 sfrTMOD=0x89; 定时器方式选择寄存器 sfrTL0=0x8A; 定时器 0 低八位 sfrTL1=0x8B; 定时器 1 低八位 sfrTH0=0x8C; 定时器 0 高八位 sfrTH1=0x8D; 定时器 1 高八位 sfrIE=0xA8; 中断允许寄存器 sfrIP=0xB8; 中断优先级寄存器 sfrSCON=0x98; 串行控制寄存器 sfrSBUF=0x99; 串行数据缓冲器 /*BITRegister*/ /*PSW*/ 程序状态字 sbitCY=0xD7; 有无进位或者借位 sbitAC=0xD6;AuxiliaryCarry 有无低四位向高四位的进位或借位 sbitF0=0xD5; 用户管理的标志位,可根据自己的需求设定 sbitRS1=0xD4; 这两位用于选择当前工作寄存器区。 8051 有 8 个 8 位寄存器 R0~R7 ,它们在 RAM 中的地址可以根据用户需要来确定。  sbitRS0=0xD3;RS1RS0 : R0~R7 的地址   00 : 00H~07H    01 : 08H~0FH    10 : 10H~17H    11 : 18H~1FH sbitOV=0xD2; 溢出标志位 sbitP=0xD0; 奇偶校验位 1 的个数为奇数, P=1 ; /*TCON*/ 定时器 / 计数器控制寄存器 sbitTF1=0x8F; 定时器 / 计数器 1 溢出中断请求标志,当溢出时由硬件置位,当 CPU 响应中断时由硬件清 0 sbitTR1=0x8E; 启动定时器 1 sbitTF0=0x8D; 定时器 / 计数器 0 溢出中断请求标志,当溢出时由硬件置位,当 CPU 响应中断时由硬件清 0 sbitTR0=0x8C; 启动定时器 0 sbitIE1=0x8B; 外部中断 1 请求标志位,产生中断时由硬件置位,当 CPU 响应中断时由硬件清 0 sbitIT1=0x8A; 外部中断 1 的触发方式选择位,当 IT1=1 时, INT1 引脚上从高到低的负跳变触发中断,当 IT1=0 时, INT1 引脚上的低电平触发中断 sbitIE0=0x89; 外部中断 0 请求标志位,产生中断时由硬件置位,当 CPU 响应中断时由硬件清 0 sbitIT0=0x88; 外部中断 0 的触发方式选择位,当 IT0=1 时, INT0 引脚上从高到低的负跳变触发中断,当 IT0=0 时, INT1 引脚上的低电平触发中断 /*IE*/ 中断允许寄存器 sbitEA=0xAF; 中断总控制位 sbitES=0xAC; 串行口中断允许位 sbitET1=0xAB; 定时器 / 计数器 1 溢出中断允许位 sbitEX1=0xAA; 外部中断 1 的溢出允许位 sbitET0=0xA9; 定时器 / 计数器 0 溢出中断允许位 sbitEX0=0xA8; 外部中断 0 的溢出允许位 /*IP*/ 中断优先级寄存器 sbitPS=0xBC; 串行口中断优先级控制位 sbitPT1=0xBB; 定时器 / 计数器 1 中断优先级控制位 sbitPX1=0xBA; 外部中断 1 中断优先级控制位 sbitPT0=0xB9; 定时器 / 计数器 0 中断优先级控制位 sbitPX0=0xB8; 外部中断 0 中断优先级控制位 /*P3*/ sbitRD=0xB7; 外部 RAM 写选通信号(输出) sbitWR=0xB6; 外部 RAM 写选通信号(输入) sbitT1=0xB5; 计数器 1 计数输入 sbitT0=0xB4; 计数器 0 计数输入 sbitINT1=0xB3; 外部中断 1 输入 sbitINT0=0xB2; 外部中断 0 输入 sbitTXD=0xB1; 串行数据发送口 sbitRXD=0xB0; 串行数据接收口 /*SCON*/ 串行口中断控制寄存器 sbitSM0=0x9F; SM0 和 SM1 控制串行口的工作方式。 00 (方式 0 ):移位寄存器方式 sbitSM1=0x9E; (用于扩展 I/O 口) ;01( 方式 1) : 8 位 UART, 波特率可变; 10 (方式 2 ): 9 位 UART, 波特率为 f/64 或 f/32;11 (方式 3 ): 9 位 UART, 波特率为 f/64 或 f/32 sbitSM2=0x9D; 允许方式 2 和方式 3 进行多机通信控制位。 sbitREN=0x9C; 允许串行接收控制位 sbitTB8=0x9B; 工作在方式 2 和方式 3 时要发送的第九位数据 sbitRB8=0x9A; 工作在方式 2 和方式 3 时要接收的第九位数据 sbitTI=0x99; 串行口接收中断请求标志位,当串行口接收完一帧数据后请求中断,由硬件置位,软件清零 sbitRI=0x98; 串行口发送中断请求标志位,当串行口发送完一帧数据后请求中断,由硬件置位,软件清零
687 次阅读|0 个评论
分享 SPI
白丁 2014-7-14 22:36
module spi_ctrl( clk,rst_n, spi_miso,spi_mosi,spi_clk, spi_tx_en,spi_tx_rdy,spi_rx_en,spi_rx_rdy,spi_tx_db,spi_rx_db ); input clk;//FPAG输入时钟信号25MHz input rst_n;//FPGA输入复位信号 input spi_miso;//SPI主机输入从机输出数据信号 output spi_mosi;//SPI主机输出从机输入数据信号 output spi_clk;//SPI时钟信号,由主机产生 input spi_tx_en;//SPI数据发送使能信号,高有效 output spi_tx_rdy;//SPI数据发送完成标志位,高有效 input spi_rx_en;//SPI数据接收使能信号,高有效 output spi_rx_rdy;//SPI数据接收完成标志位,高有效 input spi_tx_db;//SPI数据发送寄存器 output spi_rx_db;//SPI数据接收寄存器 //模拟SPI的时序模式为CPOL=1, CPHA=1,模拟速率为25Mbit //------------------------------------------------- //SPI时序控制计数器,所有SPI时序由该计数器值控制 reg cnt8;//SPI时序控制计数器,计数范围在0-18 always @(posedge clk or negedge rst_n) if(!rst_n) cnt8 = 5'd0; else if(spi_tx_en || spi_rx_en) begin if(cnt8 5'd18)cnt8 = cnt8+1'b1;//SPI工作使能 else ;//计数到18停止,等待撤销spi使能 end else cnt8 = 5'd0;//SPI关闭,计数停止 //------------------------------------------------- //SPI时钟信号产生 reg spi_clkr;//SPI时钟信号,由主机产生 always @(posedge clk or negedge rst_n) if(!rst_n) spi_clkr = 1'b1; else if(cnt8 5'd1 cnt8 5'd18) spi_clkr = ~spi_clkr;//在cnt8处于2-17时SPI时钟有效翻转 assign spi_clk = spi_clkr; //------------------------------------------------- //SPI主机输出数据控制 reg spi_mosir;//SPI主机输出从机输入数据信号 always @(posedge clk or negedge rst_n) if(!rst_n) spi_mosir = 1'b1; else if(spi_tx_en) begin case(cnt8 )//主机发送8bit数据 4'd1: spi_mosir = spi_tx_db ;//发送bit7 4'd2: spi_mosir = spi_tx_db ;//发送bit6 4'd3: spi_mosir = spi_tx_db ;//发送bit5 4'd4: spi_mosir = spi_tx_db ;//发送bit4 4'd5: spi_mosir = spi_tx_db ;//发送bit3 4'd6: spi_mosir = spi_tx_db ;//发送bit2 4'd7: spi_mosir = spi_tx_db ;//发送bit1 4'd8: spi_mosir = spi_tx_db ;//发送bit0 default: spi_mosir = 1'b1;//spi_mosi没有输出时应保持高电平 endcase end else spi_mosir = 1'b1;//spi_mosi没有输出时应保持高电平 assign spi_mosi = spi_mosir; //------------------------------------------------- //SPI主机输入数据控制 reg spi_rx_dbr;//SPI主机输入从机输出数据总线寄存器 always @(posedge clk or negedge rst_n) if(!rst_n) spi_rx_dbr = 8'hff; else if(spi_rx_en) begin case(cnt8)//主机接收并锁存8bit数据 5'd3: spi_rx_dbr = spi_miso;//接收bit7 5'd5: spi_rx_dbr = spi_miso;//接收bit6 5'd7: spi_rx_dbr = spi_miso;//接收bit5 5'd9: spi_rx_dbr = spi_miso;//接收bit4 5'd11: spi_rx_dbr = spi_miso;//接收bit3 5'd13: spi_rx_dbr = spi_miso;//接收bit2 5'd15: spi_rx_dbr = spi_miso;//接收bit1 5'd17: spi_rx_dbr = spi_miso;//接收bit0 default: ; endcase end assign spi_rx_db = spi_rx_dbr; //------------------------------------------------- //SPI数据发送完成标志位,高有效 assign spi_tx_rdy = (cnt8 == 5'd18)/* spi_tx_en)*/; //------------------------------------------------- //SPI数据接收完成标志位,高有效 assign spi_rx_rdy = (cnt8 == 5'd18)/* spi_rx_en)*/; endmodule
个人分类: FPGA|593 次阅读|0 个评论
分享 TQ2440裸跑-GPIO
热度 1 霹雳之火 2014-7-13 09:36
0实验环境与实验例程 实验环境:TQ2440 实验例程:韦东山 嵌入式linux应用开发完全手册 1 原理图 控制LED1~4的引脚为GPB5~8 当GPB5~8 输出低电平点亮相应的LED ,当GPB5~8 输出高电平点相应的LED熄灭 kn按下输入0,弹开输入1; K1控制GPF1输入,K2控制GPF4输入,K3控制GPF2输入,K4控制GPF0输入。 2 数据手册 GPB相关寄存器的设置;GPBDAT初始化是寄存器值undef 3 总结 寄存器的按位设置(bitn) 置0:R = ~(1n) 置1:R|=(1n) 4 问题及解决方法: 现象:nandflash启动时几个LED都亮 原因:因为GPBDAT复位时寄存器值undef(不定) TQ2440关于length of the file is too big问题解决 背景: 测试自己写的一个小裸机程序 led.bin :控制一个led灯。 下载: 用nor flash的u-boot的某一个选项通过USB下载(下载软件为DNW)将 led.bin 烧写到sdram中。 遇到的问题: 下载成功,可是烧写失败:length of the file is too big。 解决: 不能用DNW下载(据说是DNW的一个BUG,不能下载太小的程序),而应该用TFTP烧写。 ============================================================================= 接下来遇到的问题: 用TFTP烧写(我使用的是TftpWin)时遇到的问题:开发板能与主机互通,可是总是烧写失败--T T T T T 解决: 先查看主机69端口是否开启。 5扩展流水灯 例程下载: led流水灯(从左到右,从右到左循环)ledliushui.rar
个人分类: TQ2440|589 次阅读|2 个评论
分享 STM32的寄存器地址映像
huanghai381 2014-7-10 11:59
在 【中文】STM32F系列ARM内核32位高性能微控制器参考手册V10_1 的表一
个人分类: STM32技术文档|242 次阅读|0 个评论
分享 LPC1768 学习(三)时钟配置及节拍定时器探索篇
黄腾酒 2014-7-5 19:51
年前,买了一块LPC1768的开发板,这是我第一次真正的接触 ARM ,随板子一起来的还有一些例程,第一个例程是一个流水灯程序,这个程序涉及到时钟配置,节拍定时器,GPIO口配置,我决定从这个例程开始入门。 程序执行的第一步是复位,复位完成后初始化时钟,这个我在《 LPC1768 学习(一)系统初始化 》中提过,CPU时钟是有锁相环0和CPU时钟配置寄存器共同决定的。锁相环可以把外部时钟倍频到较高频率,PLL0输出频率是: Fcco = (2xMxFin)/N; M值是PLL0CFG寄存器中MSEL0(倍频值)加一,N值NSEL0(预分频值)加一。N值得取值范围是1~32,而M的取值是在较高的振荡器频率下(超过1MHz)允许范围是6~512。 得到PLL0输出值之后,在经过CPU时钟配置寄存器就可以得到CPU时钟。 在这个system_lpc17xx.c文件中,修改#define PLL0CFG_Val 0x00050063的宏定义值就可以了。 例如:00050063这个状态下PLL0输出400MHz。 M = 0x63(16进制) + 1 = 100(10进制); N = 0x05 + 1 = 6; Fcco = 2X12x100/6 = 400M 在经过CPU时钟配置寄存器4分频就变成100M。 在路虎的程序中我发现一个比较好的地方,就是利用时钟节拍定时器定时。 在主函数中写下如下语句就能让节拍定时器1ms中断一次。 if (SysTick_Config(SystemCoreClock / 1000))/1ms进入一次中断/ { while (1); /* 错误情况下就停在这里,对于一个while(1)死循环表示难受,但是还是保留吧 */ } 这个函数的原型是 __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1) SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ SysTick-LOAD = ticks - 1; /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ SysTick-VAL = 0; /* Load the SysTick Counter Value */ SysTick-CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0); /* Function successful */ } #define __INLINE __inline #define __STATIC_INLINE static __inline 这个函数的修饰一看就明白,静态内连,但是编译器怎么解释还是看标准是怎么定的,inline是C99标准,想具体了解,可以移步http://blog.csdn.net/hanchaoman/article/details/7270345,这里写的比较清楚。 这个函数就不解释,就是节拍函数的初始化,需要提一下的是这个函数的形参SystemCoreClock /1000,SystemCoreClock 是CPU频率,假设是100M的情况下,100M/1000 = 100K,节拍定时器在100M的时钟下计数100K次,1S可以溢出1000次,就是说1ms溢出一次,所以就是定时1ms。如果想定时10ms,就把除数改成100。
个人分类: LPC1768|6449 次阅读|0 个评论
分享 裸机S3C6410显示控制器(2)-RGB模式下初始化显示控制器 【转载】
liufan 2014-7-2 09:50
LCD在工作之前必须作一些初始化。下面讲的是在使用RGB模式时的主要初始化工作。 (1)LCD各引脚的GPIO设置 RGB接口的信号如图: (2)设置LCD的大小、工作模式、时序等。 LCD的时序图: 查看LCD的手册,找出相应的VSPW,VBPD,VFPD,HSPW,HBPD,HFPD等值,将这些值设置到VIDTCON0, VIDTCON1, VIDTCON2及部分VIDCON0寄存器中。 示例代码: view plain copy oLcdc.m_uLcdHSz=320; oLcdc.m_uLcdVSz=240; oLcdc.m_uVidOutFormat=VIDOUT_RGBIF; oLcdc.m_uDitherMode=RDITHPOS_8BIT|GDITHPOS_8BIT|BDITHPOS_8BIT; oLcdc.m_uDitherMode=~DITHERING_ENABLE; LcdcOutp32(rVIDCON1,IHSYNC_INVERT|IVSYNC_INVERT|IVDEN_INVERT); //Check LcdcOutp32(rVIDTCON0,VBPDE(VBPD_LTV350QV)|VBPD(VBPD_LTV350QV)|VFPD(VFPD_LTV350QV)|VSPW(VSPW_LTV350QV)); LcdcOutp32(rVIDTCON1,VFPDE(VFPD_LTV350QV)|HBPD(HBPD_LTV350QV)|HFPD(HFPD_LTV350QV)|HSPW(HSPW_LTV350QV)); LcdcOutp32(rVIDTCON2,LINEVAL(oLcdc.m_uLcdVSz-1)|HOZVAL(oLcdc.m_uLcdHSz-1)); LcdcOutp32(rDITHMODE,oLcdc.m_uDitherMode); //FixedDitheringMatrix (3)设置LCD的时钟源、时钟分频 VSYNC是帧频率,HSYNC是行频率,VCLK是显示控制器行扫描时使用的频率,我们要设置的就是这个频率,通过设置寄存器VIDCON0的CLKVAL字段来设置VCLK的频率。 CLKVAL字段就是LCD时钟源的分频,它们的关系如下图所示: 要计算CLKVAL的值,先假设LCD的输出频率为60Hz,能过下面的公式可以得出CLKVAL: 示例代码: view plain copy //------------------------------------------------------------ //FunctionName:LCD_GetClkValAndClkDir // //FunctionDesctiption: //Thisfunctioncalculatesclkvalanddeterminesclocksource // //Input:uLcdHSz,lcdhorizontalsize //uLcdVSz,lcdverticalsize // //Output:uClkVal,clockvalueforwantedvclk //uClkDir,clocksource // //Version: //------------------------------------------------------------ void LCD_GetClkValAndClkDir(u32uLcdHSz,u32uLcdVSz,u32*uClkVal,u32*uClkDir,CLK_SRCeClkSrc) { double dTmpVal,dVclkSrc; u32uTotalTime; if (eClkSrc==SRC_HCLK) { LCD_SetClkSrc(SRC_HCLK); dVclkSrc=g_HCLK; //shouldbechangedinyoursystemclockcondition } else if (eClkSrc==SRC_MOUT_EPLL) { LCD_SetClkSrc(SRC_MOUT_EPLL); dVclkSrc=97700000; //shouldbechangedinyoursystemclockcondition } else if (eClkSrc==SRC_DOUT_MPLL) { LCD_SetClkSrc(SRC_DOUT_MPLL); dVclkSrc=100000000; //shouldbechangedinyoursystemclockcondition } else if (eClkSrc==SRC_FIN_EPLL) { LCD_SetClkSrc(SRC_FIN_EPLL); dVclkSrc=12000000; //shouldbechangedinyoursystemclockcondition } else if (eClkSrc==SRC_27M) dVclkSrc=27000000; #if(LCD_MODULE_TYPE==LTP700WV_RGB||LCD_MODULE_TYPE==LTE480WV_RGB) uLcdHSz+=HBPD_LTP700WV+HFPD_LTP700WV+HSPW_LTP700WV+3; uLcdVSz+=VBPD_LTP700WV+VFPD_LTP700WV+VSPW_LTP700WV+3; #elif(LCD_MODULE_TYPE==LTS222QV_SRGB) uLcdHSz=uLcdHSz*3+HBPD_LTS222QV+HFPD_LTS222QV+HSPW_LTS222QV+3; uLcdVSz+=VBPD_LTS222QV+VFPD_LTS222QV+VSPW_LTS222QV+3; #elif(LCD_MODULE_TYPE==LTV300GV_RGB) uLcdHSz+=HBPD_LTV300GV+HFPD_LTV300GV+HSPW_LTV300GV+3; uLcdVSz+=VBPD_LTV300GV+VFPD_LTV300GV+VSPW_LTV300GV+3; #elif(LCD_MODULE_TYPE==LTV350QV_RGB) uLcdHSz+=HBPD_LTV350QV+HFPD_LTV350QV+HSPW_LTV350QV+3; uLcdVSz+=VBPD_LTV350QV+VFPD_LTV350QV+VSPW_LTV350QV+3; #endif uTotalTime= #if(LCD_MODULE_TYPE==LTS222QV_CPU) CS_SETUP_TIME+WR_SETUP_TIME+WR_ACT_TIME+WR_HOLD_TIME+4; #else 1; #endif dTmpVal=dVclkSrc/( double )(uTotalTime*uLcdHSz*uLcdVSz*LCD_FRM_RATE)-1; dTmpVal=(dTmpVal+0.5)*10; *uClkVal=( int )(dTmpVal/10.0); *uClkDir=(*uClkVal1)?0:1; }
个人分类: ARM|848 次阅读|0 个评论
分享 2014.6.4
dai277530706 2014-6-4 16:31
近一个半月总任务:六月份六级尽量努力吧!一个半月瘦下3.5kg。一个半月上手STM32(跟着学习战舰开发板并独立进行各模块简单程序编写),完成老师布置的任务 昨日任务: 1、英语清零吧!开始听两份听力、写一篇作文 2、看看stm32pdf,15页+ 3、找靖哥哥运动 三个俯卧撑 20个仰卧起坐 4、1:00前把手机放掉充电,睡觉! 5、明早7点起床! 昨日完成: 1、英语还是提不起兴致,做了三篇阅读,两份翻译和一份听力。。作文啊作文!胖子加油啊! 2、看stm32pdf,看了流水灯的部分,前面的到时候补上 3、靖哥哥和我去运动了,但是昨天萎极了,就拉了几下,蹬腿等,没跑步。 4、昨个不了一下英语,擦,后来失眠了,两点半睡的 5、今天6:45起来的,早起运动跑了两圈,拿了早餐券。就推了一个,貌似需要休息调整一下。 额外完成:a、去校医院准备打疫苗,说让我周五早八点去验血。b、把门禁登记了一下。 今日任务: 1、有个论坛想找我当版主,新的论坛,自己也在刚开始学习stm32,那就去做版主吧,一起成长。 2、晚上上党课,英语就写一篇作文吧!一定要写了!!! 3、看看stm32pdf,看多少看情况 4、不是很想运动,到时看看动的起来不 4、1:00前把手机放掉充电,睡觉! 5、明早6:50点起床! (和你的纠缠令我无力前行, 你看不到未来,我也看不到未来。 我需要的是鼓励,而不是贬低!I BELIEVE I CAN!I‘M THE BEST!)
个人分类: 每日计划|1 次阅读|0 个评论
分享 PWM对齐方式
007云梦 2014-4-3 20:19
左对齐方式: 脉冲计数器为循环递增计数,初值为0。使能PWM后,计数器从0开始对时钟信号计数,开始一个输出周期, 当计数值与占空比常数寄存器相等时,比较器1输出有效,将触发器置位,而计数器继续计数, 当计数器与周期常数寄存器相等时,比较器2输出有效,将触发器复位,计数器也复位,结束一个输出周期 中心对齐方式: 在此方式下,脉冲计数器为双向计数,初值为0 当PWM使能后,计数器从0开始对时钟信号递增计数,开始输出一个周期,当计数器与占空比常数寄存器相等时 比较器1输出有效,触发器翻转,而计数器继续计数,当计数值与周期常数相等时,比较器2输出有效,此时改变 计数器的计数方向,使其递减计数,当计数器再次与占空比常数相等时,比较器输出有效,使触发器再次翻转,而 计数器继续递减计数,等待计数器减会至0,完成一个周期
个人分类: MSP430|1151 次阅读|0 个评论
分享 [原创]嵌入式平台LCD 液晶屏底层时序调试的一种方法
liufan 2014-2-1 01:36
[原创]嵌入式平台LCD 液晶屏底层时序调试的一种方法
嵌入式平台 LCD 液晶屏底层时序调试的一种方法 ---原创(转载请留出处) 在用 ARM 的驱动 LCD 的时候,首先要做的就是将一块全新的屏进行驱动时序的调试,如果每次都将修改好了参数再烧录,一操作繁琐,二不直观。想到一个比较好的方法,说一说,其实很简单,就是在单步调试的状态下,手工修改 LCD 相关寄存器的值,实时看效果。是用 ADS 的朋友,可能知道,在 ADS 下,设备外设寄存器只能通过 MEM 窗口查看,需要手工输入寄存器地址,很是繁琐,而且不直观,也容易看错。方法如下: 定义一个基于寄存器字段的位定义联合体类型,以 S 3C 2440 的 LCD 控制器为例,和 LCD 时序相关的寄存器是, LCDCON2 , LCDCON3 , LCDCON4 ,定义如下。 /*** LCDCON2 - LCDCON2 Register; 0x4d000004 ***/ typedef union { int Word; struct { int bVSPW: 6; // 低位 int bVFPD: 8; int bLINEVAL: 10; int bVBPD: 8; // 高位 } Bits; } LCDCON2STR; 如果用过飞思卡尔 MCU 的朋友,对这个应该不会陌生,这是参照了飞思卡尔 MCU 寄存器定义的方式做的。用起来很爽的,呵呵。有兴趣的朋友可以找找飞思卡尔 MCU 的芯片头文件看看。可以学到不少东西。接着往下, LCDCON3 , LCDCON4 的定义如下: /*** LCDCON3 - LCDCON3 Register; 0x4d000008 ***/ typedef union { int Word; struct { int bLineblank_hfpd: 8; int bHozval: 11; int bWdly_hbpd: 7; int rev1: 6; // 未定义的位 } Bits; } LCDCON3STR; /*** LCDCON4 - LCDCON4 Register; 0x4d 00000C ***/ typedef union { int Word; struct { int bWLH_HSPW: 8; int bMVAL: 8; int rev1: 16; } Bits; } LCDCON4STR; 如何使用呢?有经验的朋友,肯定能想到使用指针,是的,哈哈,卖关子啦。就是指针啦。通过定义一个相关联合体指针,然后赋予寄存器绝对地址,如下: volatile LCDCON2STR* LcdC_2 =(volatile LCDCON2STR *)rLCDCON2; volatile LCDCON3STR* LcdC_3= (volatile LCDCON3STR *)rLCDCON3; volatile LCDCON4STR* LcdC_4= (volatile LCDCON4STR *)rLCDCON4; 或者如下: volatile LCDCON2STR* LcdC_2 =(volatile LCDCON2STR *)0x4d000004; volatile LCDCON3STR* LcdC_3= (volatile LCDCON3STR *)0x4d000008; volatile LCDCON4STR* LcdC_4= (volatile LCDCON4STR *)0x4d 00000C ; 那么在调试的时候,就可以在 ADS 中通过添加变量的方式来查看相关寄存器的值,在调试挂起状态的时候,就可以方便的用手工修改相关寄存器位域的值,很简单,很直观,见下图的变量显示: 在挂起调试的时候,通过实时修改这些值,能实时的看到 LCD 上面的显示是否正确。 直到显示正确,然后记录下那些位域的值,再回写到你的底层驱动配置代码中去。一次就搞定啦。呵呵。我这里使用的是 TQ2440 的板子,我这里以官方发布的裸奔测试进行了添加,文件名是 TQ2440_Test_20100607 ,通过宏开关来使能调试功能,限于篇幅,我只把变动的部分贴上来。很简单。只需要改改 main.c 文件就可以了。 在 main.c 文件中添加: #define DEBUG_LCD // 调试 LCD 开关,不用的话,注释掉就可了。 #ifdef DEBUG_LCD #include "lcd_tft.h" /* 联合体定义的外设寄存器 */ /*** LCDCON2 - LCDCON2 Register; 0x4d000004 ***/ typedef union { int Word; struct { int bVSPW: 6; int bVFPD: 8; int bLINEVAL: 10; int bVBPD: 8; } Bits; } LCDCON2STR; //#define _LCDCON2 (*(volatile LCDCON2STR *)0x4d000004) #define LCDCON2 _LCDCON2.Word #define LCDCON2_VBPD _LCDCON2.Bits.bVBPD #define LCDCON2_LINEVAL _LCDCON2.Bits.bLINEVAL #define LCDCON2_VFPD _LCDCON2.Bits.bVFPD #define LCDCON2_VSPW _LCDCON2.Bits.bVSPW /*** LCDCON3 - LCDCON3 Register; 0x4d000008 ***/ typedef union { int Word; struct { int bLineblank_hfpd: 8; int bHozval: 11; int bWdly_hbpd: 7; int rev1: 6; } Bits; } LCDCON3STR; //#define _LCDCON3 (*(volatile LCDCON3STR *)0x4d000008) #define LCDCON3 _LCDCON3.Word #define LCDCON3_LINEBLANK _LCDCON3.Bits.bLineblank_hfpd #define LCDCON3_HFPD _LCDCON3.Bits.bLineblank_hfpd #define LCDCON3_HOZVAL _LCDCON3.Bits.bHozval #define LCDCON3_HBPD _LCDCON3.Bits.bWdly_hbpd #define LCDCON3_WDLY _LCDCON3.Bits.bWdly_hbpd /*** LCDCON4 - LCDCON4 Register; 0x4d 00000C ***/ typedef union { int Word; struct { int bWLH_HSPW: 8; int bMVAL: 8; int rev1: 16; } Bits; } LCDCON4STR; //#define _LCDCON4 (*(volatile LCDCON4STR *)0x4d 00000C ) #define LCDCON4 _LCDCON4.Word #define LCDCON4_WLH _LCDCON4.Bits.bWLH_HSPW #define LCDCON4_HSPW _LCDCON4.Bits.bWLH_HSPW #define LCDCON4_MVAL _LCDCON4.Bits.bMVAL #define GUI_BLUE 0xFF0000 #define GUI_GREEN 0x00FF00 #define GUI_RED 0x0000FF #define GUI_CYAN 0xFFFF00 // 青色 #define GUI_MAGENTA 0xFF00FF // 品红 #define GUI_YELLOW 0x00FFFF #define GUI_WHITE 0xFFFFFF #define GUI_BLACK 0x000000 #define RGB2RGB565(rgb) ((WORD)(((((WORD)((rgb)3))(0x 1F ))11) \ |((((WORD)((rgb)10))(0x 3F ))5) \ |(((WORD)((rgb)19))(0x 1F )))) //===================================================================// volatile LCDCON2STR* LcdC_2; volatile LCDCON3STR* LcdC_3; volatile LCDCON4STR* LcdC_4; extern void Glib_FilledRectangle(int x1,int y1,int x2,int y2,int color); #define RECT_BOX_WITHD 3 #define RECT_BOX_COLOR RGB2RGB565(GUI_YELLOW) #define RECT_COLOR RGB2RGB565(GUI_BLUE) //===================================================================// #endif 在 main 函数修改如下:只添加了红色部分代码 void Main (void) { char *mode; int i; U8 key; U32 mpll_val = 0 ; //U32 divn_upll = 0 ; #if ADS10 // __rt_lib_init(); //for ADS 1.0 #endif Port_Init(); Isr_Init(); i = 2 ; //don't use 100M ! switch ( i ) { case 0: //200 key = 12; mpll_val = (9212)|(44)|(1); break; case 1: //300 key = 13; mpll_val = (6712)|(14)|(1); break; case 2: //400 key = 14; mpll_val = (9212)|(14)|(1); break; case 3: //440!!! key = 14; mpll_val = (10212)|(14)|(1); break; default: key = 14; mpll_val = (9212)|(14)|(1); break; } //init FCLK= 400M , so change MPLL first ChangeMPllValue((mpll_val12)0xff, (mpll_val4)0x 3f , mpll_val3); ChangeClockDivider(key, 12); cal_cpu_bus_clk(); consoleNum = 0; // Uart 1 select for debug. Uart_Init( 0,115200 ); Uart_Select( consoleNum ); Beep(2000, 100); Uart_SendByte('\n'); Uart_Printf("***************************************\n"); Uart_Printf(" TQ2440 Test Program\n"); Uart_Printf(" www.embedsky.net\n"); // Uart_Printf(" Build time is: %s %s\n", __DATE__ , __TIME__ ); Uart_Printf("***************************************\n"); rMISCCR=rMISCCR~(13); // USBD is selected instead of USBH1 rMISCCR=rMISCCR~(113); // USB port 1 is enabled. rDSC0 = 0x2aa; rDSC1 = 0x2aaaaaaa; //Enable NAND, USBD, PWM TImer, UART0,1 and GPIO clock, //the others must be enabled in OS!!! rCLKCON = 0xfffff0; MMU_Init(); // pISR_SWI=(_ISR_STARTADDRESS+0xf0); //for pSOS Led_Display(0x66); mode="DMA"; Clk0_Disable(); Clk1_Disable(); mpll_val = rMPLLCON; //============================================================================= #ifndef DEBUG_LCD Lcd_TFT_Init() ; // LCD initial #else Lcd_Init(); Lcd_PowerEnable(0, 1); Lcd_EnvidOnOff(1); //turn on vedio Glib_FilledRectangle(0,0,LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1,RECT_BOX_COLOR); Glib_FilledRectangle( RECT_BOX_WITHD, RECT_BOX_WITHD, LCD_XSIZE_TFT-1-RECT_BOX_WITHD, LCD_YSIZE_TFT-1-RECT_BOX_WITHD, RECT_COLOR); LcdC_2 = (volatile LCDCON2STR *)rLCDCON2; LcdC_3 = (volatile LCDCON3STR *)rLCDCON3; LcdC_4 = (volatile LCDCON4STR *)rLCDCON4; #endif //============================================================================= download_run=1; //The default menu is the Download Run mode. while(1) { #ifndef DEBUG_LCD U8 idx; Uart_Printf("\nPlease select function : \n"); for(i=0; CmdTip .fun!=0; i++) Uart_Printf("%d : %s\n", i, CmdTip .tip); idx = Uart_GetIntNum_GJ() ; if(idxi) { (*CmdTip .fun)(); Delay(20); Uart_Init( 0,115200 ); } #endif } } 编译后,加载进 SDRAM 或者 FALSH ,将 3 个指针变量添加进变量表中,然后全速运行,再点击挂起。进入单步运行模式,然后就可以直接修改相关位域进行 LCD 的时序的调试了。程序不要运行。 关于联合体位域的其他应用说明 /* 联合体定义的外设寄存器 */ /*** LCDCON2 - LCDCON2 Register; 0x4d000004 ***/ typedef union { int Word; struct { int bVSPW: 6; int bVFPD: 8; int bLINEVAL: 10; int bVBPD: 8; } Bits; } LCDCON2STR; #define _LCDCON2 (*(volatile LCDCON2STR *)0x4d000004) #define LCDCON2 _LCDCON2.Word #define LCDCON2_VBPD _LCDCON2.Bits.bVBPD #define LCDCON2_LINEVAL _LCDCON2.Bits.bLINEVAL #define LCDCON2_VFPD _LCDCON2.Bits.bVFPD #define LCDCON2_VSPW _LCDCON2.Bits.bVSPW 这个联合体下方的定义,可以在应用中,方便我们编程和调试,很直观。把 2 种应用方式列一下: 方式 1 : LCDCON2_VBPD = VBPD; LCDCON2_LINEVAL = LINEVAL_TFT; LCDCON2_VFPD = VFPD; LCDCON2_VSPW = VSPW; 方式 2 : rLCDCON2 = (VBPD 24)|(LINEVAL_TFT 14)|(VFPD 6)|(VSPW); 方式 1 和 2 实现了同样的功能。很明显,方式 1 非常直观和方便。 朋友,由此你是否想将你的 MCU 的寄存器头文件都定义成这样子呢?呵呵。 如果你真那么干的话,千万不要忘记给我传一份你定义好的头文件啊!
个人分类: ARM|1369 次阅读|0 个评论

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-4-3 14:50 , Processed in 0.105588 second(s), 19 queries , Gzip On, MemCache On.

Powered by EEWORLD电子工程世界

© 2020 http://bbs.eeworld.com.cn/

返回顶部