查看: 362|回复: 2

[分享] MCXA366VLL自制板IIC完全用TRAE AI写

[复制链接]
  • TA的每日心情
    无聊
    昨天 08:38
  • 签到天数: 705 天

    连续签到: 1 天

    [LV.9]以坛为家II

    105

    主题

    1834

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    4969

    热心会员

    最后登录
    2026-11-10
    发表于 2026-9-18 14:30:57 | 显示全部楼层 |阅读模式
    本帖最后由 胤幻1988 于 2026-9-18 14:30 编辑

    MCXA366VLL自制板IIC完全用TRAE AI写。
    我也是第一次搞这玩意,之前都是用豆包查查啥原型函数,分析些小故障。
    但是抖音天天刷到AI画板子,AI写程序,搞的我都有点焦虑了。看舆论,大家都说国外的啥CODEX,Cursor,Copilot比较好,但是咱没这个条件!
    只能用国产的TRAE。
    我把板子的原理图和MCXA366规格书发给TRAE,然后要求他根据原理图,给板上的24C04写程序。
    A11.png
    AI的逻辑还是很清晰的,它先读PDF确定了IIC的引脚,然后再去查这几个引脚的复用情况,然后读当前程序
    里面外设的使用情况,然后就是一顿代码输出。一开始对应IIC等待延时,它定义的是局部变量,结果不正常。
    还是会卡在SDK里面的等待函数里面,然后它自己做了调整,写了全局的延时,它在MDK宏定义里面,添加了
    CONFIG_I2C_RETRY_TIMES=2000000,这个也是NXP SDK留给用户的定义接口。
    然后测试,正常了。
    AI自己思考:
    A2.jpg
    A1.jpg
    AI写的C文件:
    1. /*
    2. * Copyright 2026 NXP
    3. *
    4. * SPDX-License-Identifier: BSD-3-Clause
    5. */

    6. /* 必须在 fsl_lpi2c.h 被包含之前定义:把驱动内部的无限等待改成有限
    7. * 超时(默认 I2C_RETRY_TIMES=0 会死循环)。总线异常时返回 timeout,
    8. * 不会把整个系统卡死。值为等待循环次数,远大于正常传输所需。 */
    9. #ifndef CONFIG_I2C_RETRY_TIMES
    10. #define CONFIG_I2C_RETRY_TIMES 2000000U
    11. #endif

    12. #include "fsl_device_registers.h"
    13. #include "fsl_lpi2c.h"
    14. #include "fsl_port.h"
    15. #include "fsl_clock.h"
    16. #include "fsl_reset.h"
    17. #include "at24c04.h"
    18. #include <string.h>

    19. /*******************************************************************************
    20. * 本地配置
    21. ******************************************************************************/
    22. /*! LPI2C 外设实例 */
    23. #define EEPROM_LPI2C            LPI2C2
    24. /*! I2C 引脚(ALT3 = LPI2C2) */
    25. #define EEPROM_I2C_PORT         PORT1
    26. #define EEPROM_SDA_PIN          8U
    27. #define EEPROM_SCL_PIN          9U
    28. /*! LPI2C2 源时钟:FRO_LF_DIV = 12MHz,分频 1 */
    29. #define EEPROM_CLK_FREQ         12000000U
    30. /*! I2C 总线速率 */
    31. #define EEPROM_BAUDRATE         100000U
    32. /*! 页写入大小 */
    33. #define EEPROM_PAGE_SIZE        16U
    34. /*! 单块字节数(A8 选择的 256 字节区域) */
    35. #define EEPROM_BLOCK_BYTES      256U
    36. /*! EEPROM 总容量 */
    37. #define EEPROM_TOTAL_BYTES      512U
    38. /*! 块0/块1 的 7 位从地址。
    39. *  AT24C04 器件地址字节 = 1010 A8 A1 A0 R/W,A1=A0=0(接地):
    40. *    A8=0 -> 8位 0xA0 -> 7位 0x50;A8=1 -> 8位 0xA2 -> 7位 0x51。
    41. *  注意 LPI2C API 用 7 位地址(内部左移),块1是 0x51 不是 0x52。 */
    42. #define EEPROM_SLAVE_BLOCK0     0x50U
    43. #define EEPROM_SLAVE_BLOCK1     0x51U
    44. /*! ACK 轮询最大次数(每次间隔粗略 0.2ms,共约 12ms,大于 tWR=5ms) */
    45. #define EEPROM_ACK_POLL_MAX     60U

    46. /*******************************************************************************
    47. * 内部函数
    48. ******************************************************************************/
    49. /*!
    50. * @brief  根据 EEPROM 地址取 7 位从地址
    51. *         bit8(A8)=0 -> 0x50;A8=1 -> 0x51
    52. */
    53. static uint16_t EEPROM_GetSlaveAddress(uint16_t memAddr)
    54. {
    55.     uint16_t addr;

    56.     if ((memAddr & (uint16_t)0x0100U) != 0U)
    57.     {
    58.         addr = EEPROM_SLAVE_BLOCK1;
    59.     }
    60.     else
    61.     {
    62.         addr = EEPROM_SLAVE_BLOCK0;
    63.     }
    64.     return addr;
    65. }

    66. /*!
    67. * @brief  粗略忙等待
    68. * @note   故意不用 board.c 的 my_10usDelay():它会把 my_10usDelayCnt
    69. *         清零,而 LED 非阻塞闪烁正以该计数器为时间基准,清零会打乱
    70. *         LED 的 500ms 节拍。这里只做粗略间隔(供 ACK 轮询),不影响
    71. *         任何全局计数器。
    72. */
    73. static void EEPROM_ShortBusyWait(uint32_t loops)
    74. {
    75.     volatile uint32_t i;

    76.     for (i = 0U; i < loops; i++)
    77.     {
    78.         __NOP();
    79.     }
    80. }

    81. /*!
    82. * @brief  ACK 轮询等待器件内部写周期完成
    83. *         烧写期间器件不响应地址(NACK),完成后恢复 ACK。
    84. *         只发 START + 器件地址(W) + STOP(subaddressSize/dataSize 均为 0)。
    85. * @retval kStatus_Success 器件已应答;kStatus_Timeout 超时
    86. */
    87. static status_t EEPROM_AckPoll(uint16_t slaveAddress)
    88. {
    89.     lpi2c_master_transfer_t xfer;
    90.     uint32_t tries;
    91.     status_t result = kStatus_Timeout;

    92.     (void)memset(&xfer, 0, sizeof(xfer));
    93.     xfer.slaveAddress = slaveAddress;
    94.     xfer.direction    = kLPI2C_Write;
    95.     xfer.flags        = kLPI2C_TransferDefaultFlag;

    96.     for (tries = 0U; tries < EEPROM_ACK_POLL_MAX; tries++)
    97.     {
    98.         if (LPI2C_MasterTransferBlocking(EEPROM_LPI2C, &xfer) == kStatus_Success)
    99.         {
    100.             result = kStatus_Success;
    101.             break;
    102.         }
    103.         /* 粗略约 0.2ms 后重试(@240MHz,约 10000 次循环) */
    104.         EEPROM_ShortBusyWait(10000U);
    105.     }
    106.     return result;
    107. }

    108. /*******************************************************************************
    109. * Public API
    110. ******************************************************************************/
    111. void AT24C04_Init(void)
    112. {
    113.     lpi2c_master_config_t masterConfig;

    114.     /* 1) PORT1 时钟与复位 */
    115.     CLOCK_EnableClock(kCLOCK_GatePORT1);
    116.     RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn);

    117.     /* 2) I2C 引脚复用:P1_8 SDA / P1_9 SCL,均为 ALT3。
    118.      *    I2C 开漏输出由 LPI2C 外设驱动,外部已有 4.7K 上拉。 */
    119.     PORT_SetPinMux(EEPROM_I2C_PORT, EEPROM_SDA_PIN, kPORT_MuxAlt3);
    120.     PORT_SetPinMux(EEPROM_I2C_PORT, EEPROM_SCL_PIN, kPORT_MuxAlt3);

    121.     /* 3) 开启两个引脚的输入缓冲(PCR IBE=1)。
    122.      *    本芯片 PORT 输入缓冲默认关闭;LPI2C 主机要靠 SCL 回读做
    123.      *    时钟同步、靠 SDA 回读判断 ACK/仲裁,不开 IBE 会读到恒低电平,
    124.      *    START 后永远等不到 SCL 拉高而死等(写法与 uart4.c 一致)。 */
    125.     EEPROM_I2C_PORT->PCR[EEPROM_SDA_PIN] =
    126.         ((EEPROM_I2C_PORT->PCR[EEPROM_SDA_PIN] & (~PORT_PCR_IBE_MASK)) | PORT_PCR_IBE(1U));
    127.     EEPROM_I2C_PORT->PCR[EEPROM_SCL_PIN] =
    128.         ((EEPROM_I2C_PORT->PCR[EEPROM_SCL_PIN] & (~PORT_PCR_IBE_MASK)) | PORT_PCR_IBE(1U));

    129.     /* 4) LPI2C2 时钟:挂 12MHz FRO_LF_DIV,分频 1,开时钟门控,解复位 */
    130.     CLOCK_AttachClk(kFRO_LF_DIV_to_LPI2C2);
    131.     CLOCK_SetClockDiv(kCLOCK_DivLPI2C2, 1U);
    132.     CLOCK_EnableClock(kCLOCK_GateLPI2C2);
    133.     RESET_ReleasePeripheralReset(kLPI2C2_RST_SHIFT_RSTn);

    134.     /* 5) 主机配置:100kHz 标准模式 */
    135.     LPI2C_MasterGetDefaultConfig(&masterConfig);
    136.     masterConfig.baudRate_Hz = EEPROM_BAUDRATE;
    137.     LPI2C_MasterInit(EEPROM_LPI2C, &masterConfig, EEPROM_CLK_FREQ);
    138. }

    139. status_t AT24C04_WriteByte(uint16_t addr, uint8_t data)
    140. {
    141.     return AT24C04_Write(addr, &data, 1U);
    142. }

    143. status_t AT24C04_ReadByte(uint16_t addr, uint8_t *data)
    144. {
    145.     if (data == NULL)
    146.     {
    147.         return kStatus_InvalidArgument;
    148.     }
    149.     return AT24C04_Read(addr, data, 1U);
    150. }

    151. status_t AT24C04_Write(uint16_t addr, const uint8_t *data, uint16_t len)
    152. {
    153.     status_t result = kStatus_Success;

    154.     if ((data == NULL) || (len == 0U))
    155.     {
    156.         return kStatus_InvalidArgument;
    157.     }
    158.     /* 地址 + 长度不能超出 512 字节容量(先转 32 位防止加法溢出) */
    159.     if (((uint32_t)addr + (uint32_t)len) > EEPROM_TOTAL_BYTES)
    160.     {
    161.         return kStatus_InvalidArgument;
    162.     }

    163.     while (len > 0U)
    164.     {
    165.         lpi2c_master_transfer_t xfer;
    166.         uint16_t pageOffset;
    167.         uint16_t pageRemain;
    168.         uint16_t chunk;

    169.         /* 计算当前 16 字节页内还能写多少,自动跨页;
    170.          * addr % 16 在跨块(0x0FF->0x100)时同样成立 */
    171.         pageOffset = (uint16_t)(addr % EEPROM_PAGE_SIZE);
    172.         pageRemain = (uint16_t)(EEPROM_PAGE_SIZE - pageOffset);
    173.         chunk      = (len < pageRemain) ? len : pageRemain;

    174.         (void)memset(&xfer, 0, sizeof(xfer));
    175.         xfer.slaveAddress   = EEPROM_GetSlaveAddress(addr);
    176.         xfer.direction      = kLPI2C_Write;
    177.         xfer.subaddress     = (uint32_t)(addr & 0x00FFU);  /* 1 字节字地址 */
    178.         xfer.subaddressSize = 1U;
    179.         xfer.data           = (void *)data;
    180.         xfer.dataSize       = chunk;
    181.         xfer.flags          = kLPI2C_TransferDefaultFlag;

    182.         result = LPI2C_MasterTransferBlocking(EEPROM_LPI2C, &xfer);
    183.         if (result != kStatus_Success)
    184.         {
    185.             break;
    186.         }

    187.         /* 等待本页内部烧写完成,再写下一页 */
    188.         result = EEPROM_AckPoll(xfer.slaveAddress);
    189.         if (result != kStatus_Success)
    190.         {
    191.             break;
    192.         }

    193.         addr += chunk;
    194.         data += chunk;
    195.         len  -= chunk;
    196.     }
    197.     return result;
    198. }

    199. status_t AT24C04_Read(uint16_t addr, uint8_t *buf, uint16_t len)
    200. {
    201.     status_t result = kStatus_Success;

    202.     if ((buf == NULL) || (len == 0U))
    203.     {
    204.         return kStatus_InvalidArgument;
    205.     }
    206.     if (((uint32_t)addr + (uint32_t)len) > EEPROM_TOTAL_BYTES)
    207.     {
    208.         return kStatus_InvalidArgument;
    209.     }

    210.     while (len > 0U)
    211.     {
    212.         lpi2c_master_transfer_t xfer;
    213.         uint16_t blockOffset;
    214.         uint16_t blockRemain;
    215.         uint16_t chunk;

    216.         /* 单块内连续读在 256 字节处回绕,因此跨块(0x0FF->0x100)
    217.          * 必须分两次传输。计算当前块内剩余可读字节。 */
    218.         blockOffset = (uint16_t)(addr % EEPROM_BLOCK_BYTES);
    219.         blockRemain = (uint16_t)(EEPROM_BLOCK_BYTES - blockOffset);
    220.         chunk       = (len < blockRemain) ? len : blockRemain;

    221.         (void)memset(&xfer, 0, sizeof(xfer));
    222.         xfer.slaveAddress   = EEPROM_GetSlaveAddress(addr);
    223.         xfer.direction      = kLPI2C_Read;
    224.         xfer.subaddress     = (uint32_t)(addr & 0x00FFU);  /* 1 字节字地址 */
    225.         xfer.subaddressSize = 1U;
    226.         xfer.data           = buf;
    227.         xfer.dataSize       = chunk;
    228.         xfer.flags          = kLPI2C_TransferDefaultFlag;

    229.         result = LPI2C_MasterTransferBlocking(EEPROM_LPI2C, &xfer);
    230.         if (result != kStatus_Success)
    231.         {
    232.             break;
    233.         }

    234.         addr += chunk;
    235.         buf  += chunk;
    236.         len  -= chunk;
    237.     }
    238.     return result;
    239. }
    复制代码
    AI写的H文件:
    1. /*
    2. * Copyright 2026 NXP
    3. *
    4. * SPDX-License-Identifier: BSD-3-Clause
    5. */

    6. #ifndef _AT24C04_H_
    7. #define _AT24C04_H_

    8. #include "fsl_common.h"

    9. /*******************************************************************************
    10. * 说明
    11. * AT24C04D I2C EEPROM 驱动(4Kbit = 512 字节)
    12. *
    13. * 硬件映射(依据核心板原理图 SCH_MCXA366_100P_CoreBoard_2026-08-31,U5):
    14. *   SDA -> P1_8 / LPI2C2_SDA (ALT3,R29 4.7K 上拉到 +3V3)
    15. *   SCL -> P1_9 / LPI2C2_SCL (ALT3,R28 4.7K 上拉到 +3V3)
    16. *   A0/A1 引脚接地;WP 接地(写保护关闭,可正常写入)
    17. *
    18. * 器件地址(7 位,AT24C04 地址 = 1010 A8 A1 A0 R/W):
    19. *   块0:地址 0x000~0x0FF,A8=0,从地址 0x50
    20. *   块1:地址 0x100~0x1FF,A8=1,从地址 0x51
    21. *   字地址为 1 字节,A8 通过从地址位选择。
    22. *
    23. * 器件参数:
    24. *   页写入大小 16 字节;内部写周期 tWR 最大 5ms
    25. *   I2C 速率配置为 100 kHz 标准模式
    26. *
    27. * @note 写函数内部会阻塞等待(ACK 轮询,每页最多约 5ms),
    28. *       仅在主循环 / 普通任务上下文调用,不要在中断中调用。
    29. ******************************************************************************/

    30. #if defined(__cplusplus)
    31. extern "C" {
    32. #endif /* __cplusplus */

    33. /*!
    34. * @brief  初始化 AT24C04:配置 P1_8/P1_9 复用 ALT3、LPI2C2 时钟(12MHz)、
    35. *         主机模式 100kHz。
    36. */
    37. void AT24C04_Init(void);

    38. /*!
    39. * @brief  向指定地址写入一个字节(内部等待写周期完成)
    40. * @param  addr EEPROM 地址,范围 0x000~0x1FF
    41. * @param  data 待写入字节
    42. * @retval kStatus_Success 成功;其他值为失败(超时 / 参数错误 / NACK)
    43. */
    44. status_t AT24C04_WriteByte(uint16_t addr, uint8_t data);

    45. /*!
    46. * @brief  从指定地址读取一个字节
    47. * @param  addr EEPROM 地址,范围 0x000~0x1FF
    48. * @param  data 输出读取的字节
    49. * @retval kStatus_Success 成功;其他值为失败
    50. */
    51. status_t AT24C04_ReadByte(uint16_t addr, uint8_t *data);

    52. /*!
    53. * @brief  向 EEPROM 写入任意长度数据
    54. *         内部自动按 16 字节页边界切分,并自动处理块0/块1
    55. *         (0x0FF 到 0x100)的从地址切换,每页写完后 ACK 轮询等待。
    56. * @param  addr 起始地址,范围 0x000~0x1FF
    57. * @param  data 待写入数据
    58. * @param  len  字节数;要求 addr + len 不超过 512
    59. * @retval kStatus_Success 成功;其他值为失败
    60. */
    61. status_t AT24C04_Write(uint16_t addr, const uint8_t *data, uint16_t len);

    62. /*!
    63. * @brief  从 EEPROM 读取任意长度数据(顺序读)
    64. *         内部自动处理块0/块1边界(单块内连续读在 256 字节处回绕,
    65. *         跨块时分两次传输)。
    66. * @param  addr 起始地址,范围 0x000~0x1FF
    67. * @param  buf  接收缓冲
    68. * @param  len  字节数;要求 addr + len 不超过 512
    69. * @retval kStatus_Success 成功;其他值为失败
    70. */
    71. status_t AT24C04_Read(uint16_t addr, uint8_t *buf, uint16_t len);

    72. #if defined(__cplusplus)
    73. }
    74. #endif /* __cplusplus */

    75. #endif /* _AT24C04_H_ */
    复制代码
    经过测试:
    A3.jpg
    给我的感觉还是很不错,看了以后这个趋势越来越明显了。

    hello_world_AI.rar (1.74 MB, 下载次数: 0)
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2020-12-18 12:56
  • 签到天数: 55 天

    连续签到: 1 天

    [LV.5]常住居民I

    254

    主题

    553

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    2834
    最后登录
    2026-11-6
    发表于 2026-9-18 15:55:11 | 显示全部楼层
    看起来不错,可以让他写点小的电机应用试试看,需要人来改动的地方多不多
    签到
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 21:25
  • 签到天数: 1484 天

    连续签到: 40 天

    [LV.10]以坛为家III

    3

    主题

    7024

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    11096
    最后登录
    2026-11-10
    发表于 2026-9-18 23:20:42 | 显示全部楼层
    这种IIC小程序网上大把,AI应该也是拿来主义吧,应该让AI从分析硬件电路和系统需求出发,写出整个工程的完整程序
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2026-11-11 02:46 , Processed in 0.089718 second(s), 24 queries , Redis On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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