在线时间376 小时
UID3135871
注册时间2016-10-9
NXP金币97

TA的每日心情 | 怒 2025-5-29 09:38 |
---|
签到天数: 632 天 连续签到: 1 天 [LV.9]以坛为家II
版主
  
- 积分
- 4470

- 最后登录
- 2025-6-10
|
今天收到了购买的逐飞LPC55S69 IOT开发板。唉,还是有点忍不住叹气,当时有点脑袋发热就买了。我主要对其不满的是,板上连最小板标配的IIC 的EEPROM和SPI 的FLASH都没有。不带仿真器就算了,连这2基本的外设都没,你让我怎么更新字库,大点的空间开销会不会不够。叹气归叹气,自己种的苦果,含泪也要吃完。CMSIS-DAP 是ARM官方推出的仿真通讯协议,理论通吃M系列。这下仿真烧写器,倒是有现成的。
买板子的主要目的就是在LPC55S69上面移植GUI,并看下效果如何。150M的频率其实也并不是很高,但是属性低分辨率应该也还行吧。废话不多说,开始工作。先连接好CMSIS-DAP的SWD和串口和板上的SWD和串口0对应的连接起来。逐飞LPC55S69 IOT的这块板,它自己有二次封装了官方的SDK,那就用它封装的库先看看吧,毕竟这也是板子附加值的一部分呢。
打开GPIO模拟SPI驱动LCD的例子:
编译,直接对main里面ili9341_init()右击go to definition,WTF,怎么没反应。之前在网上看到谁MDK的AC6编译器对中文并不是那么友好,只要是支持的编码格式与之前的发生了变化。我把路径改成英文,再次go to definition,这下可以跳转了。我们跳转到GPIO的控制定义代码:
- #define ILI9341_SCLK_PIN {PIO1, PIN02} // 在这里指定 SCLK_PIN 默认 P1.02
- #define ILI9341_RST_PIN {PIO1, PIN03} // 在这里指定 RST_PIN 默认 P1.03
- #define ILI9341_SDIN_PIN {PIO0, PIN26} // 在这里指定 SDIN_PIN 默认 P0.26
- #define ILI9341_CS_PIN {PIO1, PIN01} // 在这里指定 CS_PIN 默认 P1.01
- #define ILI9341_DC_PIN {PIO1, PIN04} // 在这里指定 DC_PIN 默认 P1.04
- #define ili9341_sclk(n) zf_gpio_output(sclk_pin[0], sclk_pin[1], n)
- #define ili9341_rst(n) zf_gpio_output(rst_pin[0], rst_pin[1], n)
- #define ili9341_sdin(n) zf_gpio_output(sdin_pin[0], sdin_pin[1], n)
- #define ili9341_cs(n) zf_gpio_output(cs_pin[0], cs_pin[1], n)
- #define ili9341_dc(n) zf_gpio_output(dc_pin[0], dc_pin[1], n)
- static uint16_t point_color = BLACK; // 默认画点颜色
- static uint16_t back_color = WHITE; // 背景色
- static const uint8_t sclk_pin[2] = ILI9341_SCLK_PIN;
- static const uint8_t rst_pin[2] = ILI9341_RST_PIN;
- static const uint8_t sdin_pin[2] = ILI9341_SDIN_PIN;
- static const uint8_t cs_pin[2] = ILI9341_CS_PIN;
- static const uint8_t dc_pin[2] = ILI9341_DC_PIN;
复制代码 发现它将一个引脚变量配置成了个2个元素的一维数值,并将元素分别于端口和引脚关联起来。先#define ILI9341_SCLK_PIN,然后又把ILI9341_SCLK_PIN赋给sclk_pin[2] ,然后最终#define ili9341_sclk(n) zf_gpio_output(sclk_pin[0], sclk_pin[1], n)。
但是真没看出这样有啥优点,个人觉得还有点绕。直接一步到位也挺好的。 #define ili9341_sclk(n) zf_gpio_output(PIO1, PIN02, n) 。
原本NXP官方库里面,对引脚写的函数:
- static inline void GPIO_PinWrite(GPIO_Type *base, uint32_t port, uint32_t pin, uint8_t output)
- {
- base->B[port][pin] = output;
- }
复制代码 Seekfree库里面的:
- void zf_gpio_output (group_index_list group_index, pin_index_list pin_index, bool level)
- {
- if(level)
- {
- GPIO->SET[group_index] |= // 对应管脚置位寄存器
- (0x00000001 << pin_index); // 对应管脚 bit 写 1 置位
- }
- else
- {
- GPIO->CLR[group_index] |= // 对应管脚复位寄存器
- (0x00000001 << pin_index); // 对应管脚 bit 写 1 复位
- }
- }
复制代码 我们查看到2者控制的寄存器并不一样,我们定位到GPIO的结构体:
- /** GPIO - Register Layout Typedef */
- typedef struct {
- <font color="#ff0000"> __IO uint8_t B[2][32]; /**< Byte pin registers for all port GPIO pins, array offset: 0x0, array step: index*0x20, index2*0x1 */</font>
- uint8_t RESERVED_0[4032];
- __IO uint32_t W[2][32]; /**< Word pin registers for all port GPIO pins, array offset: 0x1000, array step: index*0x80, index2*0x4 */
- uint8_t RESERVED_1[3840];
- __IO uint32_t DIR[2]; /**< Direction registers for all port GPIO pins, array offset: 0x2000, array step: 0x4 */
- uint8_t RESERVED_2[120];
- __IO uint32_t MASK[2]; /**< Mask register for all port GPIO pins, array offset: 0x2080, array step: 0x4 */
- uint8_t RESERVED_3[120];
- __IO uint32_t PIN[2]; /**< Port pin register for all port GPIO pins, array offset: 0x2100, array step: 0x4 */
- uint8_t RESERVED_4[120];
- __IO uint32_t MPIN[2]; /**< Masked port register for all port GPIO pins, array offset: 0x2180, array step: 0x4 */
- uint8_t RESERVED_5[120];
- <font color="#ff0000"> __IO uint32_t SET[2]; /**< Write: Set register for port. Read: output bits for port, array offset: 0x2200, array step: 0x4 */</font>
- uint8_t RESERVED_6[120];
- <font color="#ff0000"> __O uint32_t CLR[2]; /**< Clear port for all port GPIO pins, array offset: 0x2280, array step: 0x4 */</font>
- uint8_t RESERVED_7[120];
- __O uint32_t NOT[2]; /**< Toggle port for all port GPIO pins, array offset: 0x2300, array step: 0x4 */
- uint8_t RESERVED_8[120];
- __O uint32_t DIRSET[2]; /**< Set pin direction bits for port, array offset: 0x2380, array step: 0x4 */
- uint8_t RESERVED_9[120];
- __O uint32_t DIRCLR[2]; /**< Clear pin direction bits for port, array offset: 0x2400, array step: 0x4 */
- uint8_t RESERVED_10[120];
- __O uint32_t DIRNOT[2]; /**< Toggle pin direction bits for port, array offset: 0x2480, array step: 0x4 */
- } GPIO_Type;
复制代码 我们打开参考手册:
B寄存器的介绍(按BYTE读写GPIO):
W寄存器(按字或者半字读写GPIO)
SET、CLR、NOT寄存器的介绍:
这样一比较,两者功能几乎一样,但是B寄存器一个BYTE对应一个引脚,写寄存器时仅最后一个Bit有效。但SET、CLR、NOT每一个BIT对应引脚。
为啥这样设计,也没想明白何种场合会用到。当然直接对B寄存器控制,代码会比较简洁一点。
在读取GPIO引脚上也能很好的体现:
NXP:
- static inline void GPIO_PinWrite(GPIO_Type *base, uint32_t port, uint32_t pin, uint8_t output)
- {
- base->B[port][pin] = output;
- }
复制代码 Seekfree:
- bool zf_gpio_read (group_index_list group_index, pin_index_list pin_index)
- {
- uint32_t data = GPIO->PIN[group_index]; // 读取对应组别状态寄存器
- return ((uint8_t)(data >> pin_index) & 0x00000001); // 返回对应管脚状态
- }
复制代码
这里的延时函数,没有向通常一样用systick ,而是用了utick。LPC55S69一共有3个systick也是够变态。utick虽然跟主时钟不是完全同步,有少许延时,但也够用了。而且我觉得utick这个定时器设定的其实还是挺巧妙的。可能我少见多怪。
没有重载数据的寄存器,但时CTL寄存器里面最高位为REPEAT标志,0:运行一次 1:重复运行。
这里Uticks时钟设置为1M,一次计数就是1us。由于被REPEAT标志占了一位,实际存放延时的只有31位。2^31=2147483648us,
即 2147s,所以下面才对输入的延时最大值做了限制。
- <blockquote>//-------------------------------------------------------------------------------------------------------------------
复制代码//-------------------------------------------------------------------------------------------------------------------
// @brief 延时函数
// @param delay_count 延时操作数
// Sample usage: delay( delay_count );
//-------------------------------------------------------------------------------------------------------------------
void delay (uint32_t delay_count)
{
#ifndef RT_THREAD
if(delay_count > 2000)
delay_count = 2000*1000000;
else
delay_count *= 1000000;
zf_utick_settick_no_interrupt(delay_count, UTICK_MODE_SINGLE);
while(!(zf_utick_get_status() & UTICK_STAT_INTR_MASK)){}
zf_utick_clear_status();
#else
rt_thread_mdelay(delay_count*1000);
#endif
}
//-------------------------------------------------------------------------------------------------------------------
// @brief 延时函数 ms 级别
// @param delay_count 延时 ms 数
// Sample usage: delay_ms( 1000 );
//-------------------------------------------------------------------------------------------------------------------
void delay_ms (uint32_t delay_count)
{
#ifndef RT_THREAD
if(delay_count > 2000000)
delay_count = 2000000*1000;
else
delay_count *= 1000;
zf_utick_settick_no_interrupt(delay_count, UTICK_MODE_SINGLE);
while(!(zf_utick_get_status() & UTICK_STAT_INTR_MASK)){}
zf_utick_clear_status();
#else
rt_thread_mdelay(delay_count);
#endif
}
怎么越写越远了,NXP库写的还是很标准的,跟参考手册对得上。上次用个国产的,把我给气的。下载例程,看看屏的刷新速度:
看起来还不错啊,不知道是因为刷单色的还是啥的,明天弄个正常图片看下。
整体而言,逐飞LPC55S69 IOT开发板的板子做工啥的还是不错的,库做的虽然有点瑕疵,但整体还是挺好的。
提个建议:下次再搞开发板,能不能,给板子做4个定位孔,并上好螺柱。
|
|