哥哥教你学嵌入式 之 智芯科技 开发板 Z20K11x系列 教程(一)
文章日志
1.写于2022/11/25(网上这块板子的教程几乎没有,呜呜呜,只得自己写了)
文章目录
1.认识开发板
2.串口相关程序代码及现象记录与思考
3.关于在一块板子上iic0和iic1主从收发例子实现
1.认识开发板
智芯官网:https://www.zhixin-semi.com/
Z20K11x系列板子介绍:
基于ARM CORTEX M0+的中低端微控制器,高达256K P FLASH + 128K D FLASH,2路CANFD接口,4路UART/LIN接口,多种封装类型,适用于车身控制、空调控制、照明控制、中小功率电机控制等各种应用
主要特点:
基于ARM CORTEX M0+
主频高达64 MHz
工作电压:2.7~5.5V
提供两块物理独立的大容量FLASH(256KB Code FLASH + 128KB Data FLASH)
32KB SRAM
2路CANFD接口,每路CAN支持64个报文邮箱
4路UART, 支持硬件LIN Frame,节省CPU负荷
高达16路DMA,适用于多路数据传输
AEC-Q100 Grade 1认证
目标应用:
电动座椅,电动车窗,电动天窗,电动尾门,门模块
空调控制
灯光控制
底盘控制,制动控制等
新能源类应用,PTC,空调压缩机,ACDC, DCDC等
无刷电机控制
其他中小型CAN节点应用等
开发板实物图:
(不得不吐槽一下,左边的烧录模块,我没有对应的线束,只得用杜邦线+我的st-link连的,太松了,经常会导致keil无法识别到设备…太耽误事了。好在后面,我把一些可以连在其他的地方的线,连其他地方就基本上解决了这个问题)
比如下面:最左边的烧录模块,我就只连了两根杜邦线,其他三根连在其他可以连的地方
(还有一个吐槽的地方,这些gpio模块,J1 J2 J3 J4,不够直观啊,要是能提供一个很直观的图就好了。尽管板子后面标的有gpio序号,但是翻来翻去,很容易导致烧录模块的线解除不良,keil识别不到设备,而且很麻烦。虽然我可以拍个照,但也要经过大脑里面一层转换,还是不太直观。)
所以,我自己花时间做了个图:
这样子舒服多了,想连哪个,直接对照着这个图就行了。
如果读者有这个开发板的话,sdk和附带的一些例子应该也是有的。
好像车规级的开发板样板都是这种样子的,很小的一块板。
2.串口相关程序代码及现象记录与思考
这块板子usb转串口模块,是串口1的,pc和板子用usb线连上就可以用了。
当然了,如果想使用其他串口模块,可以将其他串口模块对应的io连上额外的usb转ttl模块,又或者可以使用蓝牙串口模块。可以看我的另一篇博客【惊!STM32 蓝牙串口模块(H21/JDY-31) 竟如此简单!】
为什么开发板附带的例子demo,不提供串口直接打印一段字符串的接口啊。
还得自己造轮子…
//这个函数,只能打印字符串。如:uart1_print("Hello uart1_print\r\n");
void uart1_print(char *send_data)
{
/* system init */
System_Init_my_uart1();//这个初始化函数我就不贴了
uint8_t data[100];
uint8_t i = 0;
uint8_t j = 0;
while((*send_data != '\0') && (i < 100))
{
data[i] = *send_data;
send_data++;
i++;
}
for(j = 0;j < i;j++)
{
/* wait for TEMT flag bit of Line Status Register to be set */
while(RESET == UART_GetLineStatus(UART1_ID,UART_LINESTA_TEMT));
/* send data back */
UART_SendByte(UART1_ID, data[j]);
}
}
当然了,我们可以添加微型库,重写fputc方法,这样我们就可以使用printf函数啦。
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用
{
UART_SendByte(UART1_ID, ch);
while(RESET == UART_GetLineStatus(UART1_ID, UART_LINESTA_TEMT));
return ch;
}
记录下这块板子关于串口的一些现象:
//波特率 设置9600 打印会多出来一个方框字符。这里设置57600 现象消失
//如果是蓝牙串口 波特率不能太高 改为9600,但没有方框字符
奇怪,太奇怪了,9600波特率,只使用uart1_print,现象如下:
3.关于在一块板子上iic0和iic1主从收发例子实现
这里我遇到大坑了,我也不知道为什么,一块板子测试,主发送7个数据,再从接收7个数据,这个逻辑,执行起来不通。
太耗费我情绪力量了。好几天后,我试着自己重新写下逻辑,试着发送一次,接收一次,哦,居然通了。后面测试,一块板子上,一次最大传送4个数据。
master_send_buffer(I2C1_ID,txBuffer1,4);//这里测试,按照顺序执行master发送,slave接收。一次最大传输长度,为4
slave_receive_buffer(I2C0_ID,4);
master_send_buffer(I2C1_ID,txBuffer1,4);//这里测试,按照顺序执行master发送,slave接收。一次最大传输长度,为4
slave_receive_buffer(I2C0_ID,4);
然后,我试下从发送主接收。
slave_send_buffer后,master_receive_buffer,这样子是不会通的。
仔细看了下代码逻辑,从在发送前,要先主发送一个请求,Wait RD_REQ interrupt
所以,在一块板子上测试,逻辑只能自己写了。
//主 发送 读命令
I2C_MasterReadCmd(I2C1_ID,I2C_RESTART_AND_STOP_DISABLE);
/* Wait RD_REQ interrupt */
while(RESET == I2C_GetIntStatus(I2C0_ID, I2C_INT_RD_REQ));
/* Clear RD_REQ interrupt */
I2C_ClearInt(I2C0_ID, I2C_INT_RD_REQ);
/* When TX FIFO is not full, the slave sends one byte */
while(RESET == I2C_GetStatus(I2C0_ID, I2C_STATUS_TFNF));
I2C_SlaveSendByte(I2C0_ID, 0x57);
/* When RX FIFO is not empty, the master receives one byte */
while(RESET == I2C_GetStatus(I2C1_ID, I2C_STATUS_RFNE));
uint8_t master_res = I2C_ReceiveByte(I2C1_ID);
printf("===%c \r\n",master_res);
以上。