打印
[应用相关]

开发国民技术N32G43X过程中遇到的坑

[复制链接]
2262|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-6-26 08:15 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、开发环境与资料获取

使用keil开发,阔以使用VSCode下载一个扩展,看代码更舒服。

注意的是要去官方下载对应的pack芯片包,这样你才能使用keil开发。

去技术支持群找国民技术给的ftp链接/还有官网的奇怪论坛i2c啥。

二、debug时工具J-link的问题

1.如果安装的J-link版本高于keil自带的J-link版本,烧录程序会报错。



只需要去J-link的官网下载低版本的J-link驱动即可。

2.但是当J-ink的版本过低,而我们使用的芯片比较新的时候,开启debug也会报错,报错识别不到芯片内核似乎,已经解决找不到图片了。这时候你要自主选择你对应芯片的内核,比如我是M4。然后就可以解决。

三、配置ADC底层遇到问题

1.开发ADC,我是使用内部晶振。所以在ADC使用内部时钟HSI的时候,发现代码会卡在等待ADC启动。





发现是因为用了老版本的ADC库,老版本的ADC似乎还没解决这个问题。去找AE拿最新demo,把官方ADC的库替换之后,即可正常跑。

2.公司的架构代码里面有1ms的操作线程,使用的时候,没有关心到我删去了外部晶振。所以系统时钟似乎自动变成了4MHZ。而1ms线程使用的是108MHZ系统时钟,所以出现定时时间过长,程序跑的极为缓慢。

解决方法:修改系统时钟为HSI内部高速时钟,并且进行倍频至108MHZ。





去官方找到RCC设置的demo文件。进行CV。

注意开发的过程中一定要看清楚并且修改sysclock,看清楚自己的时钟选的是啥,非常重要!delay啥的都会变快或者变慢。

3.ADC的配置方面,要注意开启和关闭ADC。

4.AD数据采样方面。将采样到的AD数据可以存入一个长一点的数组如buffer[128]等,然后进行4个取一次平均啥的;或者去掉最大和最小值,然后再求平均。防止电压突变。

/*********************************************************
函数名:        unsigned int ADCRead()
描  述:        ADC转换程序,转换10次,去掉最小值和最大值,求8次平均值
输入值: 无
输出值: 无
返回值: data—ADC结果
**********************************************************/
unsigned int ADCRead()
{
        unsigned int max, min, sum, ad_temp;
        unsigned char  i;
        unsigned int data;

        max = 0x00;
        min = 0xffff;
        sum = 0x00;
        for (i=0; i<10; i++)
        {
                ad_temp = ADCConvert();

                if (ad_temp > max)
                {
                         max = ad_temp;//替换最大值
                }
                if (ad_temp < min)
                {
                        min = ad_temp;//替换最小值
                }
                sum += ad_temp;
        }
        sum -= min;
        sum -= max;
        data = sum >> 3;        //除以8,取平均值
        return data;
}
四、硬件方面

1.因为硬件设计问题即对应ADC的IO可能电压被后面的电路拉走了,后面电阻给太大了,导致ADC在读取电压的时候,AD值为0。把后面电路断开,ADC就可以正常运行了。

最终发现是USB供电,电流不足的问题。换上DCsource供电,问题解决。

2.芯片的电源与地最好都要连,这边工程师漏连了,开发过程似乎没啥问题,不过后面飞线了。

3.看手册,注意有些引脚不能悬空。

4.三色led没有串联电阻,导致IO输出电压被拉低,可能是这个问题。

最终发现是USB供电,电流不足的问题。换上DCsource供电,问题解决。

5.第一板块记得叫硬件工程师留ADC的TP点。DCsource不够的时候,记得留3.3V电源点,不然还要自己焊接。

6.非常非常重要的,不要用usb口供电,用DCsource供电!因为DCsource有限,懒的去借。直接焊接了拓展小板子,USB3.3V供电。导致ADC读取电压有问题;芯片GPIO输出能力受限,电压降低至2.0多甚至更低;

7.TP芯片电压时,可以把绿油划开来测电压。

8.测试ADC的读取的电压是否正确时,可以直接用电压表接到对应电阻或电容地方来测试电压,根据公式和参考电压选择的不同来算。

五、keil5的debug的学习

1.把数组添加到watch窗口后,可以把名字里面的"[]"去掉,就可以一次性看所有的数组数据了。

2.单步运行,进入函数内部运行,跳出函数运行等

六、软件方面学习

1.switch从0开始进入循环

2.#define宏定义语句可以直接后面加函数,逗号隔开



3.读取ADC的AD值时,需要有一些电路中的补偿值(offset),这些补偿值比较小;还有需要做一些小数运算。基于这些,可以使用左右移动来提高计算,比较的精度。比如先左移13位,计算完后再右移7位,留6位进行比较;右移13位直接作为结果。

4.尽量少在MCU中使用浮点运算,比较占用运行内存。多使用移位运算辅助计算or比较。

5.64位有符号整数除以32位有符号整数有高效。在455单片机上运行一次要20US左右,太久了。

汇编程序:无符号64位除32位的除法子程序(-百度经验 (baidu.com)

因为不是固定除数,所以不能用移位,循环减更慢。所以使用汇编代码更加快速。

6.不同单片机的定义数据变量是不同的位数。不知道怎么查看。这个要注意一下。然后不同数据类型的对比与运算好像是向上兼容再做运算。

七、开发CAN通信

1.注意CAN通信波特率的计算。翻页AN查找波特率的计算。要注意CAN通信所使用的时钟。

2.过滤器标识符的运用配置问题。使用标志位暂时替代。注意在开发CAN通信中,常常会有很多的ID,所以需要过滤一部分不需要的ID。未解决。

没有使用芯片自带的过滤器,编写代码解决。

3.CAN通信的数据在对应的结构体就可以读取,数据存在sram中。

4.在发送数据的过程中,遇到了要将电压,电流数据分为高位,低位发送到BMS端。



而我定义的存储电压和电流的变量是32位的(如下图),因为为了提高精度,做了移位处理。



所以我面临一个问题:如何将32位的数据的高低字节分别存入1个字节(即8位)?

在编写代码前,复习了下啥是高位,啥是低位,如下



比如0xFD即1111 1101 。从右到左边,是从低位到高位。



所以先将我的32位数据*10扩大精度,然后再右移6位,变回比原来的数据大10倍的数据。然后开始做取出低字节and高字节的操作。运用位运算与,将低字节的8位数据取出来。再将原本的数据右移8位,将原本数据的高8位移到低8位,再用运算与取出高8位存入低8位。

而hal_CAN_TxMessages.Data[0]是个8位大的变量。

5.在做复杂计算的时候,若有相同的部分,可以拿出来定义一个变量,避免程序重复的计算节省时间。如上图我定义了Vout与Iout。

八、PWM开发问题

项目需要一个PWM波来控制电流的输出,以为简单的配置即可,以为推挽输出的能力非常足够,实则不是。

我配置了复用推挽输出,估计是高电平输出能力不足,导致电流有几十mA的跳变,这对于项目非常不行。测试了底板转换电路;测试了小卡3.3V与12V供电是否稳定,电源的波动也会影响到PWM波输出的电压;最终拿来了一台信号发生器,将小卡PWM输出断开,接上信号发生器,发现电流稳定几mA输出。推测PWM有隐藏问题。

最终将PWM配置为上拉+复用推挽输出。解决了这个问题。

PWM上拉可以提高高电平的输出能力。

九、移位计算的精度问题

遇到了调整电池电压1V,输出的电流却没有调整,因为我们的反馈是ADC测试Vout的电压,根据电压以及电流算出实时的功率,与目标功率进行对比,然后实现恒功率。推测是精度问题。

unsigned int Iset_target_max_U5F6;
unsigned int Iset_target_max_U5F6_a;
unsigned int CONSTANT_POWER=2250;  
unsigned int meas_Vout_value_U6F6=110*64;
int main()
{
        Iset_target_max_U5F6 = ((((CONSTANT_POWER * (1 << 12)) / meas_Vout_value_U6F6)));
        Iset_target_max_U5F6_a = ((((CONSTANT_POWER * (1 << 6)) / meas_Vout_value_U6F6)) * (1 << 6));
        printf("%d\n", Iset_target_max_U5F6);
        printf("%d\n", Iset_target_max_U5F6_a);
        return 0;
}
先移位再计算,提高精度。修改目标值的计算公式之后,精度提高了,并且正常。

另外,在做移位计算的时候,一定要注意数据的类型。unsigned int 是4个字节,32位,经得起移位12位。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/Xia996/article/details/134204006

使用特权

评论回复
沙发
LEDyyds| | 2024-6-27 16:22 | 只看该作者
码住,经验,日后需要可以用

使用特权

评论回复
板凳
埃娃| | 2024-6-28 17:39 | 只看该作者
usb供电的电流真实迷啊

使用特权

评论回复
地板
suncat0504| | 2024-6-29 09:37 | 只看该作者
学习了,谢谢大佬分享经验。

使用特权

评论回复
5
结合国际经验| | 2024-8-31 19:59 | 只看该作者
开发设计和调试

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

13

粉丝