openwch / arduino_core_ch32

Core library for CH32duino
248 stars 41 forks source link

Need SPI,I2C_Master, Easy ADC on CH32V003 #29

Open Witawat opened 11 months ago

Witawat commented 11 months ago

Need SPI,I2C_Master, Easy ADC on CH32V003

maxint-rd commented 10 months ago

I2C master is working. The AT24C02 eeprom example gives a demonstration. I tested that example with a bare EEPROM chip and it worked. Note however that error handling often results in a lockup. I've experimented to improve this. To get I2C scanning working some modifications are needed. It mainly involves resetting the I2C when there is no device at the specific address. (Have something working for myself, but not ready to publish a PR yet)

0x0fe commented 9 months ago

@maxint-rd can you please share your I2C scan?

maxint-rd commented 9 months ago

Hello @0x0fe Eventually I modified /libraries/Wire/src/utility/twi.c to get the regular I2C scanning to work. Here you can find a scanning example: https://playground.arduino.cc/Main/I2cScanner/

For this fix I got inspiration from this example: https://github.com/mockthebear/easy-ch32v003/tree/main/examples/i2c_scanner

As stated before, my modifications are not ready for a PR yet. but perhaps they are useful as is. The main changes were:

These are the changes (line numbers were changed in the process, so for reference only):

:50
    #define I2C_TIMEOUT_TICK        10      // shorter timeout to facilitate I2C scanning
:276 / :290 / :304
        if((GetTick()-tickstart) > I2C_TIMEOUT_TICK) 
        {
          // To allow I2C scanning, when a start condition times out the bus needs to be released
          if(sendstop)  
            I2C_GenerateSTOP(obj->handle.Instance, ENABLE);
          return I2C_TIMEOUT;
        }
:314
if(size)   // Support for I2C scanning: allow only sending the address (without actual data)
{  
    while(size)
    {
        if( I2C_GetFlagStatus(obj->handle.Instance, I2C_FLAG_TXE) != RESET )
        {
            I2C_SendData(obj->handle.Instance, *data++);
            size--;
        }
    }

    tickstart = GetTick();
    while(!I2C_CheckEvent(obj->handle.Instance, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
        if((GetTick()-tickstart) > I2C_TIMEOUT_TICK) 
        {
          return I2C_TIMEOUT;
        }
    }
}   // if(size)
:428
      while(I2C_GetFlagStatus( obj->handle.Instance, I2C_FLAG_RXNE ) ==  RESET)
      {
        // at occasion the CH32 would just hang while reading the response. Still unknown why. but adding a timeout may prevent this
        if((GetTick()-tickstart) > I2C_TIMEOUT_TICK) 
        {
            I2C_GenerateSTOP( obj->handle.Instance, ENABLE );
            return I2C_TIMEOUT;
        }
      }
0x0fe commented 9 months ago

@maxint-rd thank you, i will make the changes on my side (i use ch32x035 though)

maxint-rd commented 9 months ago

Allright, unfortunately I have no CH32x035 to test with. I only bought a bunch of the CH32V003 and try to make the most of them. For one project I use I2C scanning to detect a slave device and then use I2C to read values to display them on an I2C-driven LCD. It works for me. Good luck with your project...

0x0fe commented 9 months ago

it should be alright, for some reason they disabled the I2C on their HAL for CH32X035, but i wil ltest soon, at least it compiles.

maxint-rd commented 9 months ago

Perhaps you need to set a configuration option somewhere in a header file. They did something similar with SPI on the CH32v003. I also needed to change the configuration of the clock selection to be able to run bare chips without external crystal.

0x0fe commented 9 months ago

@maxint-rd yes, for those interested the option to re-enable the I2C in the HAL is here : https://github.com/openwch/arduino_core_ch32/blob/f14a216b441e03907d2c0c9afab03e3985ab6852/variants/CH32X035/CH32X035G8U/variant_CH32X035G8U.h#L19

0x0fe commented 9 months ago

@maxint-rd do you mind to share your twi.c file? seems like it has changed quite a bit since and i cannot quite match your diffs.

0x0fe commented 9 months ago

@TianpeiLee Since the pinmux is somewhat limited on CH32V and CH32X series, i suggest that you add a soft i2c and soft uart (at least TX) implementation directly in the core or as libraries so that users can still use alternative pins for uart output and i2c bus. For I2C this library can be used as is, i have tested it on CH32V003 and it works fine. https://github.com/yasir-shahzad/SoftI2C/blob/master/src/SoftI2C.cpp

maxint-rd commented 9 months ago

@maxint-rd do you mind to share your twi.c file? seems like it has changed quite a bit since and i cannot quite match your diffs.

Hello @0x0fe ,

Attached is my current version: twi.zip I zipped the twi.c file to be able to attach it to this post. Note that this is my version, based on a version found in an earlier release of the WCH Arduino core. It may have been modified in the meanwhile. I marked most of my changes with a comment containing the tag "MMOLE:", but you may need to compare it to an earlier release to locate all changes. It works for me, but I can't guarantee it works for you...

maxgerhardt commented 6 months ago

@maxint-rd Can you open a PR with your changes to the Two-wire-library? Other people seem to be running into I2C issues too regarding I2C scanning, locking up after the first non-responding I2C address. Unfortunately the twi.zip you linked above just gives me a "Request has expired" error message.

0x0fe commented 6 months ago

@maxint-rd I think there is two topics, re-enabling hardware I2C, with proper mux handling so that at least the two available ports can be used, and extending twi with soft i2c, so that any pin can be used, i tested both hardware I2C ports and soft I2C, on x035, everything works fine, so it is just a matter of updating the core now, unfortunately there is no ressources allocated on this core at wch, maybe if peoples submit PR they will eventually be merged.

maxint-rd commented 6 months ago

@maxgerhardt - what do you mean by that error message? I just tried the link in the post above and it properly lets me download the zip containing my twi.c file. (BTW. A few posts higher I posted the changes I made to fix I2C scanning for my CH32V003).

I still need to install the latest core and then redo my changes. I would like to then post a PR. even though WCH hasn't really merge many of them in the past, I did see the occasional copying of suggested changes. Since I only have the CH32V003 I cannot test the others before proposing global changes.

maxint-rd commented 6 months ago

@0x0fe - you're right. From what I've read the x035 seems to have some other issues as well, including batches without I2C altogether. I've also noticed a lack of allocated resources. That's a bit unfortunate since the CH32 is a nice family of chips that could be a good addition to the Arduino ecosystem. Without sufficient support I'm afraid many potential users may get disappointed and turn away...

maxint-rd commented 5 months ago

@maxint-rd Can you open a PR with your changes to the Two-wire-library? Other people seem to be running into I2C issues too regarding I2C scanning, locking up after the first non-responding I2C address. Unfortunately the twi.zip you linked above just gives me a "Request has expired" error message.

@maxgerhardt - I saw some people asking for it on the Platformio forum. Since I don't use Platformio, I won't respond there. I recently shared my changes in a fork with a branch. All work in progress, so use at your own risk. No production quality code either, but it works for me...

I'm having some progress on getting I2C slave functions working on my CH32V003 as well. Hope to share that too (sometime...) When I do I'll probably use a shorter timeout, resulting in faster scanning too. Edit: I published something that seems to work. Those who dare can try the Wire library in this branch . I added basic examples for an I2C scanner and for a simple blinking slave. Work in progress - USE AT YOUR OWN RISK - No guarantees or support! -

Edit2: Tested ADC a bit and the regular Arduino function analogRead() seems to work.